Ouch… It hertz!
Saturday, June 30th, 2007Often times, you want to change your program’s behavior based on available CPU Mhz (or GHz as is more common nowadays). For example, Call Recorder won’t default to using AAC encoding for audio recording if your Mac is under 800 Mhz.
So let’s say you want to find out the current CPU speed. It’s common to use the ancient but useful sysctl call.
int args[] = {CTL_HW, HW_CPU_FREQ};
int freq = 0;
size_t len = sizeof(freq);
if (sysctl(args, 2, &freq, &len, NULL, 0) == 0)
printf("It's %d Hz\n", freq);
A Gold Star if you can see what’s wrong with that code.
Wait for it…
Since sysctl returns the clock speed in tiny little old Hz (1 billionth of a GHz), we’re quickly running out of space in our 32-bit int. We’d overflow an unsigned int when we hit 4,294,967,296 Hz and we’ll overflow the signed int we used in the code above at only 2,147,483,648 Hz.
But that’s only 2.14 Ghz.
So on my 2.33 Ghz MacBook Pro, the code above will return:
It’s -1,964,967,296 Hz.
Oops…
Obviously, using an unsigned int instead of a normal int would have been wiser. However, even that will overflow when clock speeds double (in 2 years if you trust Moore’s law.)
Indeed, the solution is to use a long long or int64 (whichever camp you’re from.)
Here’s better code, using sysctlbyname instead, which is the recommended way to do it nowadays:
uint64_t freq = 0;
size_t size = sizeof( freq );
if (sysctlbyname( "hw.cpufrequency_max", &freq, &size, NULL, 0 ) == 0)
printf("It's %lld Hz\n", freq);
This introduces a new overflow point when CPU speeds exceed 18,446,744,073 Ghz.
Interestingly, if you believe that Moore’s law will continue to hold, we should reach these speeds around 2071. That is, of course, assuming that the human race survives the Year 2038 Problem which will cause a similar overflow issue with the way OS X keeps track of the date seconds in an unsigned int.
Switching the date seconds to an int64 will cause a new problem in about 290 billion years.
However, due to predicted changes to the Solar System, it is not widely regarded as a pressing issue.
Also, don’t forget about good old OS 9’s Gestalt routine. You can’t use gestaltProcClkSpeed anymore for the same reason. (It returns a long.) But Gestalt also has a selector gestaltProcClkSpeedMHz, which drops the six useless zeros.
At WWDC, Glen had the unenviable task of hitting the compatibility lab and testing the upcoming release of iGlasses on as many computers as he could. When checking out the new 2.2 and 2.4 GHz MacBook Pros, he noticed something interesting about the built-in iSight:
Then, braving the 95 degree the heat, we got on our bikes and cruised down to the Cambridge Apple Store. After fighting our way through the crowds of people asking if they can pre-order an iPhone, we commandeered some MB Pros. The same test program produced a
Safari 3 on Windows is old news by now, but I still have this nagging feeling. 