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