1 | /* |
---|
2 | * ntp_unixclock.c - routines for reading and adjusting a 4BSD-style |
---|
3 | * system clock. Emacs has hide-ifdef-mode ... |
---|
4 | */ |
---|
5 | |
---|
6 | #ifdef HAVE_CONFIG_H |
---|
7 | # include <config.h> |
---|
8 | #endif |
---|
9 | |
---|
10 | #include <stdio.h> |
---|
11 | #include <sys/types.h> |
---|
12 | #ifdef HAVE_UNISTD_H |
---|
13 | # include <unistd.h> |
---|
14 | #endif /* HAVE_UNISTD_H */ |
---|
15 | #ifdef NLIST_STRUCT |
---|
16 | # include <nlist.h> |
---|
17 | # ifdef NLIST_NAME_UNION |
---|
18 | # define N_NAME n_un.n_name |
---|
19 | # else /* not NLIST_NAME_UNION */ |
---|
20 | # define N_NAME n_name |
---|
21 | # endif /* not NLIST_NAME_UNION */ |
---|
22 | #endif /* NLIST_STRUCT */ |
---|
23 | #include <sys/stat.h> |
---|
24 | #include <sys/time.h> |
---|
25 | |
---|
26 | #ifdef HAVE_SYS_PARAM_H |
---|
27 | # include <sys/param.h> |
---|
28 | #endif |
---|
29 | #ifdef HAVE_UTMP_H |
---|
30 | # include <utmp.h> |
---|
31 | #endif |
---|
32 | #ifdef HAVE_SYS_SYSCTL_H |
---|
33 | #include <sys/sysctl.h> |
---|
34 | #endif |
---|
35 | |
---|
36 | #if defined(HAVE_GETBOOTFILE) |
---|
37 | # include <paths.h> |
---|
38 | #endif |
---|
39 | |
---|
40 | #include "ntpd.h" |
---|
41 | #include "ntp_io.h" |
---|
42 | #include "ntp_unixtime.h" |
---|
43 | #include "ntp_stdlib.h" |
---|
44 | |
---|
45 | #if defined(HAVE_LIBKVM) |
---|
46 | # ifdef HAVE_SYS_PROC_H |
---|
47 | # include <sys/proc.h> |
---|
48 | # endif |
---|
49 | # include <kvm.h> |
---|
50 | # include <limits.h> |
---|
51 | |
---|
52 | # ifndef _POSIX2_LINE_MAX |
---|
53 | # define _POSIX2_LINE_MAX 2048 |
---|
54 | # endif |
---|
55 | #endif /* HAVE_LIBKVM */ |
---|
56 | |
---|
57 | #ifdef HAVE_SYS_TIMEX_H /* Linux - also HAVE___ADJTIMEX */ |
---|
58 | # include <sys/timex.h> |
---|
59 | #endif |
---|
60 | |
---|
61 | #ifdef hz /* Was: RS6000 */ |
---|
62 | # undef hz |
---|
63 | #endif /* hz */ |
---|
64 | |
---|
65 | extern int debug; |
---|
66 | /* |
---|
67 | * These routines (init_systime, get_systime, step_systime, adj_systime) |
---|
68 | * implement an interface between the (more or less) system independent |
---|
69 | * bits of NTP and the peculiarities of dealing with the Unix system |
---|
70 | * clock. These routines will run with good precision fairly independently |
---|
71 | * of your kernel's value of tickadj. I couldn't tell the difference |
---|
72 | * between tickadj==40 and tickadj==5 on a microvax, though I prefer |
---|
73 | * to set tickadj == 500/hz when in doubt. At your option you |
---|
74 | * may compile this so that your system's clock is always slewed to the |
---|
75 | * correct time even for large corrections. Of course, all of this takes |
---|
76 | * a lot of code which wouldn't be needed with a reasonable tickadj and |
---|
77 | * a willingness to let the clock be stepped occasionally. Oh well. |
---|
78 | */ |
---|
79 | extern long adj_precision; /* adj precision in usec (tickadj) */ |
---|
80 | extern long tvu_maxslew; /* maximum adjust doable in one sec (usec) */ |
---|
81 | |
---|
82 | #ifdef SYS_WINNT |
---|
83 | extern long units_per_tick; /* imported from lib/systime.c module */ |
---|
84 | #endif /* SYS_WINNT */ |
---|
85 | |
---|
86 | extern u_long tsf_maxslew; /* same as above, as long format */ |
---|
87 | |
---|
88 | extern l_fp sys_clock_offset; /* correction for current system time */ |
---|
89 | |
---|
90 | #if defined(GDT_SURVEYING) |
---|
91 | extern l_fp gdt_rsadj; /* running sum of adjustments to time */ |
---|
92 | #endif |
---|
93 | |
---|
94 | /* |
---|
95 | * Import sys_clock (it is updated in get_systime) |
---|
96 | */ |
---|
97 | extern long sys_clock; |
---|
98 | |
---|
99 | /* |
---|
100 | * Export default_tick and default_tickadj (for ntp_config) |
---|
101 | */ |
---|
102 | u_long default_tick = 0; |
---|
103 | u_long default_tickadj = 0; |
---|
104 | |
---|
105 | static void clock_parms P((u_long *, u_long *)); |
---|
106 | |
---|
107 | /* |
---|
108 | * init_systime - initialize the system clock support code, return |
---|
109 | * clock precision. |
---|
110 | * |
---|
111 | * Note that this code obtains to kernel variables related to the local |
---|
112 | * clock, tickadj and tick. The code knows how the Berkeley adjtime |
---|
113 | * call works, and assumes these two variables are obtainable and are |
---|
114 | * used in the same manner. Tick is supposed to be the number of |
---|
115 | * microseconds which are added to the system clock at clock interrupt |
---|
116 | * time when the time isn't being slewed. Tickadj is supposed to be |
---|
117 | * the number of microseconds which are added or subtracted from tick when |
---|
118 | * the time is being slewed. |
---|
119 | * |
---|
120 | * If either of these two variables is missing, or is there but is used |
---|
121 | * for a purpose different than that described, you are SOL and may have |
---|
122 | * to do some custom kludging. |
---|
123 | * |
---|
124 | * This really shouldn't be in here. |
---|
125 | */ |
---|
126 | void |
---|
127 | init_systime() |
---|
128 | { |
---|
129 | u_long tickadj; |
---|
130 | u_long tick; |
---|
131 | u_long hz; |
---|
132 | |
---|
133 | /* |
---|
134 | * Obtain the values |
---|
135 | */ |
---|
136 | #if !defined(VMS) |
---|
137 | clock_parms(&tickadj, &tick); |
---|
138 | #else |
---|
139 | { |
---|
140 | extern int get_tickfreq(int *FREQ, int *SYSTICK); |
---|
141 | int freq,systick,sts; |
---|
142 | |
---|
143 | sts = get_tickfreq(&freq,&systick); |
---|
144 | if(!(sts & 1)) lib$stop(sts); |
---|
145 | |
---|
146 | tick = 1000000/freq; /* (usec) */ |
---|
147 | } |
---|
148 | tickadj = tick/10; /* VMS_{ADJTIME,TICTIME}.C will do up to 10% */ |
---|
149 | #endif /* VMS */ |
---|
150 | #ifdef DEBUG |
---|
151 | if (debug) |
---|
152 | printf("kernel vars: tickadj = %ld, tick = %ld\n", tickadj, tick); |
---|
153 | #endif |
---|
154 | |
---|
155 | /* |
---|
156 | * If tickadj or hz wasn't found, we're doomed. If hz is |
---|
157 | * unreasonably small, forget it. |
---|
158 | */ |
---|
159 | if (tickadj == 0 || tick == 0) { |
---|
160 | msyslog(LOG_ERR, "tickadj or tick unknown, exiting"); |
---|
161 | exit(3); |
---|
162 | } |
---|
163 | if (tick > 65535) { |
---|
164 | msyslog(LOG_ERR, "tick value of %lu is unreasonably large", |
---|
165 | tick); |
---|
166 | exit(3); |
---|
167 | } |
---|
168 | |
---|
169 | /* |
---|
170 | * Estimate hz from tick |
---|
171 | */ |
---|
172 | #ifndef SYS_VXWORKS |
---|
173 | hz = 1000000L / tick; |
---|
174 | #else |
---|
175 | hz =sysClkRateGet(); |
---|
176 | #endif |
---|
177 | |
---|
178 | #ifdef SYS_WINNT |
---|
179 | if ((1000000L % tick) > tick/2) |
---|
180 | hz += 1; |
---|
181 | #endif /* SYS_WINNT */ |
---|
182 | |
---|
183 | /* |
---|
184 | * Set adj_precision and the maximum slew based on this. Note |
---|
185 | * that maxslew is set slightly shorter than it needs to be as |
---|
186 | * insurance that all slews requested will complete in one second. |
---|
187 | */ |
---|
188 | #ifdef ADJTIME_IS_ACCURATE |
---|
189 | adj_precision = 1; |
---|
190 | #else |
---|
191 | # if defined(SCO3_TICKADJ) || defined(SCO5_TICKADJ) |
---|
192 | adj_precision = tickadj * hz; |
---|
193 | # else |
---|
194 | # ifndef SYS_WINNT |
---|
195 | adj_precision = tickadj; |
---|
196 | # else |
---|
197 | /* minimum adjustment is one 100 nanosecond unit at each clock tick */ |
---|
198 | adj_precision = (long)(hz * 0.1); |
---|
199 | # endif /* SYS_WINNT */ |
---|
200 | # endif /* not SCO[35]_TICKADJ */ |
---|
201 | #endif /* ADJTIME_IS_ACCURATE */ |
---|
202 | #ifdef NEED_HPUX_ADJTIME |
---|
203 | /* |
---|
204 | * when using adjtimed daemon, need to allow more time |
---|
205 | * because daemon may not run right away |
---|
206 | */ |
---|
207 | tvu_maxslew = tickadj * (hz - 3); |
---|
208 | #else |
---|
209 | # if defined(SLEWALWAYS) && !defined(ADJTIME_IS_ACCURATE) |
---|
210 | /* |
---|
211 | * give us more time if we are always slewing... just in case |
---|
212 | */ |
---|
213 | tvu_maxslew = tickadj * (hz - 3); |
---|
214 | # else |
---|
215 | # if !defined(SYS_WINNT) && !defined(SCO3_TICKADJ) && !defined(SCO5_TICKADJ) |
---|
216 | tvu_maxslew = tickadj * (hz - 1); |
---|
217 | # else |
---|
218 | tvu_maxslew = tickadj * hz; |
---|
219 | # endif /* SYS_WINTNT */ |
---|
220 | # endif /* SLEWALWAYS */ |
---|
221 | #endif /* NEED_HPUX_ADJTIME */ |
---|
222 | if (tvu_maxslew > 999990) { |
---|
223 | /* |
---|
224 | * Don't let the maximum slew exceed 1 second in 4. This |
---|
225 | * simplifies calculations a lot since we can then deal |
---|
226 | * with less-than-one-second fractions. |
---|
227 | */ |
---|
228 | tvu_maxslew = (999990/adj_precision) * adj_precision; |
---|
229 | } |
---|
230 | TVUTOTSF(tvu_maxslew, tsf_maxslew); |
---|
231 | NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ |
---|
232 | msyslog(LOG_NOTICE, "tickadj = %d, tick = %d, tvu_maxslew = %d, est. hz = %d", |
---|
233 | tickadj, tick, tvu_maxslew, hz); |
---|
234 | #ifdef DEBUG |
---|
235 | if (debug) |
---|
236 | printf( |
---|
237 | "adj_precision = %ld, tvu_maxslew = %ld, tsf_maxslew = 0.%08lx\n", |
---|
238 | adj_precision, tvu_maxslew, tsf_maxslew); |
---|
239 | #endif |
---|
240 | |
---|
241 | /* |
---|
242 | * Set the current offset to 0 |
---|
243 | */ |
---|
244 | L_CLR(&sys_clock_offset); |
---|
245 | #if defined(GDT_SURVEYING) |
---|
246 | /* |
---|
247 | * Set the current increment |
---|
248 | */ |
---|
249 | |
---|
250 | L_CLR(&gdt_rsadj); |
---|
251 | #endif /* GDT_SURVEYING */ |
---|
252 | } |
---|
253 | |
---|
254 | |
---|
255 | #if !defined(VMS) |
---|
256 | |
---|
257 | # ifndef HZ |
---|
258 | # define HZ DEFAULT_HZ |
---|
259 | # endif |
---|
260 | |
---|
261 | # ifdef NLIST_STRUCT |
---|
262 | # ifdef NLIST_NAME_UNION |
---|
263 | # define NL_B {{ |
---|
264 | # define NL_E }} |
---|
265 | # else |
---|
266 | # define NL_B { |
---|
267 | # define NL_E } |
---|
268 | # endif |
---|
269 | # endif |
---|
270 | |
---|
271 | #define K_FILLER_NAME "DavidLetterman" |
---|
272 | |
---|
273 | /* |
---|
274 | * clock_parms - return the local clock tickadj and tick parameters |
---|
275 | * |
---|
276 | */ |
---|
277 | |
---|
278 | static void |
---|
279 | clock_parms(ptickadj, ptick) |
---|
280 | u_long *ptickadj; |
---|
281 | u_long *ptick; |
---|
282 | { |
---|
283 | u_long tick; |
---|
284 | int got_tick = 0; |
---|
285 | int got_tickadj = 0; |
---|
286 | int hz = 0; |
---|
287 | int got_hz = 0; |
---|
288 | # ifdef SYS_WINNT |
---|
289 | DWORD add, every; |
---|
290 | BOOL noslew; |
---|
291 | # else /* not SYS_WINNT */ |
---|
292 | # if defined(HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_CLOCKRATE) |
---|
293 | int mib[2]; |
---|
294 | size_t ci_len; |
---|
295 | struct clockinfo c; |
---|
296 | int rc; |
---|
297 | # endif /* HAVE_SYSCTL && CTL_KERN && KERN_CLOCKRATE */ |
---|
298 | # ifndef NOKMEM |
---|
299 | static struct nlist nl[] = |
---|
300 | { |
---|
301 | NL_B |
---|
302 | # ifdef K_TICKADJ_NAME |
---|
303 | # define N_TICKADJ 0 |
---|
304 | K_TICKADJ_NAME |
---|
305 | # else |
---|
306 | K_FILLER_NAME |
---|
307 | # endif /* K_TICKADJ_NAME */ |
---|
308 | NL_E, |
---|
309 | NL_B |
---|
310 | # ifdef K_TICK_NAME |
---|
311 | # define N_TICK 1 |
---|
312 | K_TICK_NAME |
---|
313 | # else |
---|
314 | K_FILLER_NAME |
---|
315 | # endif /* K_TICK_NAME */ |
---|
316 | NL_E, |
---|
317 | NL_B "" NL_E, |
---|
318 | }; |
---|
319 | # ifdef HAVE_K_OPEN |
---|
320 | # else /* not HAVE_K_OPEN */ |
---|
321 | # ifdef HAVE_KVM_OPEN |
---|
322 | register kvm_t *kd; |
---|
323 | # else /* not HAVE_KVM_OPEN */ |
---|
324 | register int i; |
---|
325 | int kmem; |
---|
326 | struct stat stbuf; |
---|
327 | off_t where; |
---|
328 | # ifdef HAVE_BOOTFILE |
---|
329 | const char *kernelname; |
---|
330 | # else /* not HAVE_BOOTFILE */ |
---|
331 | static char *kernelnames[] = |
---|
332 | { |
---|
333 | "/kernel/unix", |
---|
334 | "/kernel", |
---|
335 | "/vmunix", |
---|
336 | "/unix", |
---|
337 | "/mach", |
---|
338 | "/hp-ux", |
---|
339 | "/386bsd", |
---|
340 | "/netbsd", |
---|
341 | "/stand/vmunix", |
---|
342 | "/bsd", |
---|
343 | # ifdef KERNELFILE |
---|
344 | KERNELFILE, |
---|
345 | # endif |
---|
346 | NULL |
---|
347 | }; |
---|
348 | # endif /* not HAVE_BOOTFILE */ |
---|
349 | # endif /* not HAVE_KVM_OPEN */ |
---|
350 | # endif /* not HAVE_K_OPEN */ |
---|
351 | # endif /* not NOKMEM */ |
---|
352 | # endif /* not SYS_WINNT */ |
---|
353 | |
---|
354 | # ifdef SYS_WINNT |
---|
355 | if (!GetSystemTimeAdjustment(&add, &every, &noslew)) |
---|
356 | { |
---|
357 | *ptick = 0; |
---|
358 | *ptickadj = 0; |
---|
359 | return; |
---|
360 | } |
---|
361 | units_per_tick = add; |
---|
362 | # else /* not SYS_WINNT */ |
---|
363 | |
---|
364 | # if defined(HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_CLOCKRATE) |
---|
365 | mib[0] = CTL_KERN; |
---|
366 | mib[1] = KERN_CLOCKRATE; |
---|
367 | ci_len = sizeof(c); |
---|
368 | rc = sysctl(mib, 2, &c, &ci_len, NULL, 0); |
---|
369 | if (rc == -1) |
---|
370 | { |
---|
371 | NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ |
---|
372 | syslog(LOG_NOTICE, "sysctl returned %d: %m", rc); |
---|
373 | } |
---|
374 | *ptick = c.tick; |
---|
375 | ++got_tick; |
---|
376 | # ifdef HAVE_TICKADJ_IN_STRUCT_CLOCKINFO |
---|
377 | *ptickadj = c.tickadj; |
---|
378 | ++got_tickadj; |
---|
379 | # endif /* HAVE_TICKADJ_IN_STRUCT_CLOCKINFO */ |
---|
380 | # ifdef HAVE_HZ_IN_STRUCT_CLOCKINFO |
---|
381 | hz = c.hz; |
---|
382 | ++got_hz; |
---|
383 | # endif /* HAVE_HZ_IN_STRUCT_CLOCKINFO */ |
---|
384 | # endif /* HAVE_SYSCTL && CTL_KERN && KERN_CLOCKRATE */ |
---|
385 | |
---|
386 | if (!got_hz) |
---|
387 | { |
---|
388 | hz = HZ; |
---|
389 | # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) |
---|
390 | hz = (int) sysconf (_SC_CLK_TCK); |
---|
391 | # endif /* HAVE_SYSCONF && _SC_CLK_TCK */ |
---|
392 | # ifdef OVERRIDE_HZ |
---|
393 | hz = DEFAULT_HZ; |
---|
394 | # endif |
---|
395 | ++got_hz; |
---|
396 | } |
---|
397 | |
---|
398 | { |
---|
399 | # ifndef NOKMEM |
---|
400 | # ifdef HAVE_K_OPEN /* { */ |
---|
401 | if (K_open((char *)0, O_RDONLY, "/vmunix")!=0) |
---|
402 | { |
---|
403 | msyslog(LOG_ERR, "K_open failed"); |
---|
404 | exit(3); |
---|
405 | } |
---|
406 | kusenlist(1); |
---|
407 | if (knlist(nl) != 0) |
---|
408 | { |
---|
409 | msyslog(LOG_ERR, "knlist failed"); |
---|
410 | exit(3); |
---|
411 | } |
---|
412 | # else /* } not HAVE_K_OPEN { */ |
---|
413 | # ifdef HAVE_KVM_OPEN /* { */ |
---|
414 | if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL) |
---|
415 | { |
---|
416 | msyslog(LOG_ERR, "kvm_open failed"); |
---|
417 | exit(3); |
---|
418 | } |
---|
419 | if (kvm_nlist(kd, nl) == -1) |
---|
420 | { |
---|
421 | msyslog(LOG_ERR, "kvm_nlist failed"); |
---|
422 | exit(3); |
---|
423 | } |
---|
424 | # else /* } not HAVE_KVM_OPEN { */ |
---|
425 | # ifdef HAVE_GETBOOTFILE |
---|
426 | kernelname = getbootfile(); |
---|
427 | if (!kernelname) |
---|
428 | { |
---|
429 | msyslog(LOG_ERR, "getbootfile() didn't find kernel name!"); |
---|
430 | exit(3); |
---|
431 | } |
---|
432 | else if (stat(kernelname, &stbuf) == -1) |
---|
433 | { |
---|
434 | msyslog(LOG_ERR, "stat(%s) failed: %m", kernelname); |
---|
435 | exit(3); |
---|
436 | } |
---|
437 | else if (nlist(kernelname, nl) < 0) |
---|
438 | { |
---|
439 | msyslog(LOG_ERR, "nlist(%s) failed: %m", kernelname); |
---|
440 | exit(3); |
---|
441 | } |
---|
442 | # else /* not HAVE_GETBOOTFILE */ |
---|
443 | for (i = 0; kernelnames[i] != NULL; i++) |
---|
444 | { |
---|
445 | if (stat(kernelnames[i], &stbuf) == -1) |
---|
446 | continue; |
---|
447 | if (nlist(kernelnames[i], nl) >= 0) |
---|
448 | break; |
---|
449 | } |
---|
450 | if (kernelnames[i] == NULL) |
---|
451 | { |
---|
452 | msyslog(LOG_ERR, "Clock init couldn't find kernel object file"); |
---|
453 | } |
---|
454 | # endif /* not HAVE_GETBOOTFILE */ |
---|
455 | kmem = open("/dev/kmem", O_RDONLY); |
---|
456 | if (kmem < 0) |
---|
457 | { |
---|
458 | msyslog(LOG_ERR, "Can't open /dev/kmem for reading: %m"); |
---|
459 | #ifdef DEBUG |
---|
460 | if (debug) |
---|
461 | perror("/dev/kmem"); |
---|
462 | #endif |
---|
463 | } |
---|
464 | # endif /* } not HAVE_KVM_OPEN */ |
---|
465 | # endif /* } not HAVE_K_OPEN */ |
---|
466 | # endif /* not NOKMEM */ |
---|
467 | } |
---|
468 | # endif /* not SYS_WINNT */ |
---|
469 | |
---|
470 | /* Skippy says we need to know TICK before handling TICKADJ */ |
---|
471 | if (got_tick != 1) |
---|
472 | { |
---|
473 | # if defined(HAVE_SYS_TIMEX_H) && defined(HAVE___ADJTIMEX) |
---|
474 | struct timex txc; |
---|
475 | # endif /* HAVE_SYS_TIMEX_H && HAVE___ADJTIMEX */ |
---|
476 | |
---|
477 | # if !defined(NOKMEM) && defined(N_TICK) |
---|
478 | # ifdef HAVE_K_OPEN |
---|
479 | if (K_read(ptick, sizeof(*ptick), nl[N_TICK].n_value) != sizeof(*ptick)) |
---|
480 | { |
---|
481 | msyslog(LOG_ERR, "K_read tick failed"); |
---|
482 | } |
---|
483 | else |
---|
484 | { |
---|
485 | if (*ptick) ++got_tick; |
---|
486 | } |
---|
487 | # else /* not HAVE_K_OPEN */ |
---|
488 | # ifdef HAVE_KVM_OPEN |
---|
489 | if (kvm_read(kd, nl[N_TICK].n_value, (char *)ptick, sizeof(*ptick)) != |
---|
490 | sizeof(*ptick)) |
---|
491 | { |
---|
492 | msyslog(LOG_ERR, "kvm_read tick failed"); |
---|
493 | } |
---|
494 | else |
---|
495 | { |
---|
496 | if (*ptick) ++got_tick; |
---|
497 | } |
---|
498 | # else /* not HAVE_KVM_OPEN */ |
---|
499 | if ((where = nl[N_TICK].n_value) == 0) |
---|
500 | { |
---|
501 | msyslog(LOG_ERR, "Unknown kernel var <%s>", |
---|
502 | nl[N_TICK].N_NAME); |
---|
503 | } |
---|
504 | else |
---|
505 | { |
---|
506 | if (lseek(kmem, where, SEEK_SET) == -1) |
---|
507 | { |
---|
508 | msyslog(LOG_ERR, "lseek for %s fails: %m", |
---|
509 | nl[N_TICK].N_NAME); |
---|
510 | } |
---|
511 | else |
---|
512 | { |
---|
513 | if (read(kmem, ptick, sizeof(*ptick)) != sizeof(*ptick)) |
---|
514 | { |
---|
515 | msyslog(LOG_ERR, "read for %s fails: %m", |
---|
516 | nl[N_TICK].N_NAME); |
---|
517 | } |
---|
518 | else |
---|
519 | { |
---|
520 | # ifdef NLIST_EXTRA_INDIRECTION |
---|
521 | /* |
---|
522 | * Aix requires one more round of indirection |
---|
523 | * if storage class a pointer. |
---|
524 | */ |
---|
525 | if ( nl[N_TICK].n_sclass == 0x6b) |
---|
526 | { |
---|
527 | if (lseek(kmem, *ptick, SEEK_SET) == -1) |
---|
528 | { |
---|
529 | msyslog(LOG_ERR, "lseek2 for %s fails: %m", |
---|
530 | nl[N_TICK].N_NAME); |
---|
531 | } |
---|
532 | else |
---|
533 | { |
---|
534 | if (read(kmem, ptick, sizeof(*ptick)) != |
---|
535 | sizeof(*ptick)) |
---|
536 | { |
---|
537 | msyslog(LOG_ERR, "read2 for %s fails: %m", |
---|
538 | nl[N_TICK].N_NAME); |
---|
539 | } |
---|
540 | else |
---|
541 | { |
---|
542 | if (*ptick) ++got_tick; |
---|
543 | } |
---|
544 | } |
---|
545 | } |
---|
546 | # else /* not NLIST_EXTRA_INDIRECTION */ |
---|
547 | if (*ptick) ++got_tick; |
---|
548 | # endif /* not NLIST_EXTRA_INDIRECTION */ |
---|
549 | } |
---|
550 | } |
---|
551 | } |
---|
552 | # endif /* not HAVE_KVM_OPEN */ |
---|
553 | # endif /* not HAVE_K_OPEN */ |
---|
554 | # ifdef TICK_NANO |
---|
555 | if (got_tick) |
---|
556 | { |
---|
557 | *ptick /= 1000; |
---|
558 | } |
---|
559 | # endif /* TICK_NANO */ |
---|
560 | # endif /* not NOKMEM && N_TICK */ |
---|
561 | |
---|
562 | if (!got_tick && default_tick) |
---|
563 | { |
---|
564 | *ptick = default_tick; |
---|
565 | if (*ptick) ++got_tick; |
---|
566 | } |
---|
567 | |
---|
568 | # ifdef PRESET_TICK |
---|
569 | if (!got_tick) |
---|
570 | { |
---|
571 | # if defined(HAVE_SYS_TIMEX_H) && defined(HAVE___ADJTIMEX) |
---|
572 | # ifdef MOD_OFFSET |
---|
573 | txc.modes = 0; |
---|
574 | # else |
---|
575 | txc.mode = 0; |
---|
576 | # endif |
---|
577 | __adjtimex(&txc); |
---|
578 | # endif /* HAVE_SYS_TIMEX_H && HAVE___ADJTIMEX */ |
---|
579 | *ptick = (u_long) PRESET_TICK; |
---|
580 | if (*ptick) ++got_tick; |
---|
581 | } |
---|
582 | # endif /* PRESET_TICK */ |
---|
583 | |
---|
584 | if (got_tick != 1) |
---|
585 | { |
---|
586 | msyslog(LOG_ERR, "Problem getting tick: %d != 1", got_tick); |
---|
587 | exit(3); |
---|
588 | } |
---|
589 | |
---|
590 | tick = *ptick; /* This might be used by PRESET_TICKADJ */ |
---|
591 | } |
---|
592 | |
---|
593 | /* Skippy says we need to know TICK before handling TICKADJ */ |
---|
594 | if (got_tickadj != 1) |
---|
595 | { |
---|
596 | # if !defined(NOKMEM) && defined(N_TICKADJ) |
---|
597 | if (nl[N_TICKADJ].n_value == 0) |
---|
598 | { |
---|
599 | msyslog(LOG_ERR, "Unknown kernel variable <%s>", |
---|
600 | nl[N_TICKADJ].N_NAME); |
---|
601 | } |
---|
602 | else |
---|
603 | { |
---|
604 | # ifdef HAVE_K_OPEN |
---|
605 | if (K_read(ptickadj, sizeof(*ptickadj), nl[N_TICKADJ].n_value) != |
---|
606 | sizeof(*ptickadj)) |
---|
607 | { |
---|
608 | msyslog(LOG_ERR, "K_read tickadj failed"); |
---|
609 | } |
---|
610 | else |
---|
611 | { |
---|
612 | if (*ptickadj) ++got_tickadj; |
---|
613 | } |
---|
614 | # else /* not HAVE_K_OPEN */ |
---|
615 | # ifdef HAVE_KVM_OPEN |
---|
616 | if (kvm_read(kd, nl[N_TICKADJ].n_value, (char *)ptickadj, sizeof(*ptickadj)) != |
---|
617 | sizeof(*ptickadj)) |
---|
618 | { |
---|
619 | msyslog(LOG_ERR, "kvm_read tickadj failed"); |
---|
620 | } |
---|
621 | else |
---|
622 | { |
---|
623 | if (*ptickadj) ++got_tickadj; |
---|
624 | } |
---|
625 | # else /* not HAVE_KVM_OPEN */ |
---|
626 | if ((where = nl[N_TICKADJ].n_value) == 0) |
---|
627 | { |
---|
628 | msyslog(LOG_ERR, "Unknown kernel var <%s>", |
---|
629 | nl[N_TICKADJ].N_NAME); |
---|
630 | } |
---|
631 | else |
---|
632 | { |
---|
633 | if (lseek(kmem, where, SEEK_SET) == -1) |
---|
634 | { |
---|
635 | msyslog(LOG_ERR, "lseek for %s fails: %m", |
---|
636 | nl[N_TICKADJ].N_NAME); |
---|
637 | } |
---|
638 | else |
---|
639 | { |
---|
640 | if (read(kmem, ptickadj, sizeof(*ptickadj)) != |
---|
641 | sizeof(*ptickadj)) |
---|
642 | { |
---|
643 | msyslog(LOG_ERR, "read for %s fails: %m", |
---|
644 | nl[N_TICKADJ].N_NAME); |
---|
645 | } |
---|
646 | else |
---|
647 | { |
---|
648 | # ifdef NLIST_EXTRA_INDIRECTION |
---|
649 | /* |
---|
650 | * Aix requires one more round of indirection |
---|
651 | * if storage class a pointer. |
---|
652 | */ |
---|
653 | if ( nl[N_TICKADJ].n_sclass == 0x6b) |
---|
654 | { |
---|
655 | if (lseek(kmem, *ptickadj, SEEK_SET) == -1) |
---|
656 | { |
---|
657 | msyslog(LOG_ERR, "lseek2 for %s fails: %m", |
---|
658 | nl[N_TICKADJ].N_NAME); |
---|
659 | } |
---|
660 | else |
---|
661 | { |
---|
662 | if (read(kmem, ptickadj, sizeof(*ptickadj)) != |
---|
663 | sizeof(*ptickadj)) |
---|
664 | { |
---|
665 | msyslog(LOG_ERR, "read2 for %s fails: %m", |
---|
666 | nl[N_TICKADJ].N_NAME); |
---|
667 | } |
---|
668 | else |
---|
669 | { |
---|
670 | if (*ptickadj) ++got_tickadj; |
---|
671 | } |
---|
672 | } |
---|
673 | } |
---|
674 | # else /* not NLIST_EXTRA_INDIRECTION */ |
---|
675 | if (*ptickadj) ++got_tickadj; |
---|
676 | # endif /* not NLIST_EXTRA_INDIRECTION */ |
---|
677 | } |
---|
678 | } |
---|
679 | } |
---|
680 | # endif /* not HAVE_KVM_OPEN */ |
---|
681 | # endif /* not HAVE_K_OPEN */ |
---|
682 | } |
---|
683 | |
---|
684 | # ifdef TICKADJ_NANO |
---|
685 | if (got_tickadj) |
---|
686 | { |
---|
687 | *ptickadj /= 1000; |
---|
688 | if (*ptickadj == 0) |
---|
689 | { |
---|
690 | *ptickadj = 1; |
---|
691 | } |
---|
692 | } |
---|
693 | # endif /* TICKADJ_NANO */ |
---|
694 | # ifdef SCO5_TICKADJ |
---|
695 | if (got_tickadj) |
---|
696 | { |
---|
697 | *ptickadj /= (1000 * hz); |
---|
698 | } |
---|
699 | # else /* not SCO5_TICKADJ */ |
---|
700 | # ifdef SCO3_TICKADJ |
---|
701 | if (got_tickadj) |
---|
702 | { |
---|
703 | *ptickadj *= (10000 / hz); |
---|
704 | } |
---|
705 | # endif /* SCO3_TICKADJ */ |
---|
706 | # endif/* not SCO5_TICKADJ */ |
---|
707 | # endif /* not NOKMEM && N_TICKADJ */ |
---|
708 | |
---|
709 | if (!got_tickadj && default_tickadj) |
---|
710 | { |
---|
711 | *ptickadj = default_tickadj; |
---|
712 | if (*ptickadj) ++got_tickadj; |
---|
713 | } |
---|
714 | |
---|
715 | # ifdef PRESET_TICKADJ |
---|
716 | if (!got_tickadj) |
---|
717 | { |
---|
718 | *ptickadj = (u_long) ((PRESET_TICKADJ) ? PRESET_TICKADJ : 1); |
---|
719 | if (*ptickadj) ++got_tickadj; |
---|
720 | } |
---|
721 | # endif /* PRESET_TICKADJ */ |
---|
722 | |
---|
723 | if (got_tickadj != 1) |
---|
724 | { |
---|
725 | msyslog(LOG_ERR, "Problem getting tickadj: %d != 1", got_tickadj); |
---|
726 | exit(3); |
---|
727 | } |
---|
728 | } |
---|
729 | |
---|
730 | # ifndef NOKMEM |
---|
731 | # ifdef HAVE_K_OPEN |
---|
732 | (void) K_close(); |
---|
733 | # else /* not HAVE_K_OPEN */ |
---|
734 | # ifdef HAVE_KVM_OPEN |
---|
735 | if (kvm_close(kd) < 0) |
---|
736 | { |
---|
737 | msyslog(LOG_ERR, "kvm_close failed"); |
---|
738 | exit(3); |
---|
739 | } |
---|
740 | # else /* not HAVE_KVM_OPEN */ |
---|
741 | close(kmem); |
---|
742 | # endif /* not HAVE_KVM_OPEN */ |
---|
743 | # endif /* not HAVE_K_OPEN */ |
---|
744 | # endif /* not NOKMEM */ |
---|
745 | |
---|
746 | # ifdef DEBUG |
---|
747 | if (debug) |
---|
748 | printf("tick = %ld, tickadj = %ld, hz = %d\n", *ptick, *ptickadj, hz); |
---|
749 | # endif |
---|
750 | } |
---|
751 | #endif /* not VMS */ |
---|