Skip to content

Commit

Permalink
linux: use /proc/cpuinfo for CPU frequency
Browse files Browse the repository at this point in the history
Obtain the CPU frequency from /proc/cpuinfo because there may not be any
cpufreq info available in /sys. This also means that the reported CPU speed
from now on is the *maximum* speed, not the *actual* speed the CPU runs at.

This change only applies to x86 because ARM and MIPS don't report that
information in /proc/cpuinfo.

Fixes joyent#588.

This is a back-port of commit 775064a from the master branch.
  • Loading branch information
bnoordhuis committed Nov 20, 2012
1 parent 72955c2 commit 5639b2f
Showing 1 changed file with 34 additions and 14 deletions.
48 changes: 34 additions & 14 deletions src/unix/linux/linux-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,13 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
if (ci == NULL)
return uv__new_sys_error(ENOMEM);

read_speeds(numcpus, ci);
read_models(numcpus, ci);
read_times(numcpus, ci);

/* read_models() on x86 also reads the CPU speed from /proc/cpuinfo */
if (ci[0].speed == 0)
read_speeds(numcpus, ci);

*cpu_infos = ci;
*count = numcpus;

Expand All @@ -344,18 +347,26 @@ static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) {
}


/* Also reads the CPU frequency on x86. The other architectures only have
* a BogoMIPS field, which may not be very accurate.
*/
static void read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
#if defined(__i386__) || defined(__x86_64__)
static const char marker[] = "model name\t: ";
static const char model_marker[] = "model name\t: ";
static const char speed_marker[] = "cpu MHz\t\t: ";
#elif defined(__arm__)
static const char marker[] = "Processor\t: ";
static const char model_marker[] = "Processor\t: ";
static const char speed_marker[] = "";
#elif defined(__mips__)
static const char marker[] = "cpu model\t\t: ";
static const char model_marker[] = "cpu model\t\t: ";
static const char speed_marker[] = "";
#else
# warning uv_cpu_info() is not supported on this architecture.
static const char marker[] = "(dummy)";
static const char model_marker[] = "";
static const char speed_marker[] = "";
#endif
unsigned int num;
unsigned int model_idx;
unsigned int speed_idx;
char buf[1024];
char* model;
FILE* fp;
Expand All @@ -364,18 +375,27 @@ static void read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
if (fp == NULL)
return;

num = 0;
model_idx = 0;
speed_idx = 0;

while (fgets(buf, sizeof(buf), fp)) {
if (num >= numcpus)
break;

if (strncmp(buf, marker, sizeof(marker) - 1))
if (model_marker[0] != '\0' &&
model_idx < numcpus &&
strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0)
{
model = buf + sizeof(model_marker) - 1;
model = strndup(model, strlen(model) - 1); /* strip newline */
ci[model_idx++].model = model;
continue;
}

model = buf + sizeof(marker) - 1;
model = strndup(model, strlen(model) - 1); /* strip newline */
ci[num++].model = model;
if (speed_marker[0] != '\0' &&
speed_idx < numcpus &&
strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0)
{
ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
continue;
}
}
fclose(fp);
}
Expand Down

0 comments on commit 5639b2f

Please sign in to comment.