freq_adj.in revision 290001
1#! @PATH_PERL@ -w
2
3die "perl5 needed\n" unless ($] > 5);
4
5use Getopt::Std;
6use vars qw($opt_n);
7
8getopts('d:nt:');
9
10#chop($ncpu = `sysctl -n hw.ncpu`);
11#die "Found $ncpu CPUs; can only be run on systems with 1 CPU.\n" if ($ncpu > 1);
12
13$driftfile = "/etc/ntp.drift";
14$driftfile = $opt_d if defined($opt_d);
15
16chop($timer = `sysctl -n kern.timecounter.hardware 2> /dev/null`);
17
18$timer =~ tr/\U/\L/;
19
20if ($timer eq '') {
21  open(DM, "/var/run/dmesg.boot");
22  while(<DM>) {
23    # Timecounter "i8254"  frequency 1193182 Hz
24    if (/^Timecounter "(\w+)"\s+/) {
25      $timer = $1;
26      last;
27    }
28  }
29  close(DM);
30}
31
32$opt_t = $timer if !defined($opt_t);
33
34if ($timer ne '') {		# $timer found...
35  if ($opt_t ne  '') {		# - and $opt_t found
36    if ($timer ne $opt_t) {	# - - and they differ
37      warn "You specified a $opt_t timer but I detected a $timer timer.\n";
38      usage();
39      exit 1;
40    } else {			# - - and they are the same
41      ;
42    }
43  } else {			# - but no $opt_t specified; this is OK
44    ;
45  }
46} else {			# No $timer found...
47  if ($opt_t ne '') {		# - but $opt_t was specified
48    $timer = $opt_t;		# - - so use it.
49  } else {			# - and neither was $opt_t
50    warn "I can't tell what timer you have.  Please specify one.\n";
51    usage();
52    exit 1;
53  }
54}
55
56open(DF, $driftfile) || die "Can't open driftfile ($driftfile): $!\n";
57while(<DF>) {
58    chop;
59    if (/^(-?\d+\.\d+)(\s\d)?$/) {
60	$drift = $1;
61    } else {
62	die "Bogus value in driftfile $driftfile: <$_>\n";
63    }
64}
65close(DF);
66
67print "NTP drift is <$drift>\n";
68
69# Convert from NTP's idea of PPM to a decimal equivalent
70$freq_adj = int ( $drift * ( 10 ** 6 / 2 ** 20) );
71print "normalized freq_adj  is <$freq_adj>\n";
72
73$freq_adj = int ( ( $freq_adj - 1 ) / 2 );
74print "Applying freq_adj of <".-$freq_adj.">\n";
75
76$sysctl = "machdep.".$timer."_freq";
77
78chop($mach_freq = `sysctl -n $sysctl`);
79
80print "$sysctl is <$mach_freq>\n";
81
82$n_mach_freq = $mach_freq - $freq_adj;
83
84if (defined($opt_n)) {
85  print "$sysctl $mach_freq -> $n_mach_freq\n";
86} else {
87  print "i8254: ".`sysctl -w $sysctl=$n_mach_freq`;
88}
89
90sub usage {
91  print STDERR <<EOUsage
92Usage: $0 [-d drift_file] [-n] [-t timer]
93where "drift_file" defaults to /etc/ntp.drift
94and "timer" is usually "tsc" or "i8254"
95and "-n" says "don't really change anything, just say what would happen".
96EOUsage
97}
98