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