Under the heading of "How to make friends and influence people" I think that dummy CPU grabbers will put you on the "dookie" list for every tester I can imagine. I predict that within one hour of release, it will be discovered what you are doing.
Why not just write an SMP program?
1. Remove all globals that are written to (read only is fine).
2. Remove all non-reentrant junk like strtok()
3. Remove all statics that are written to
4. For anything else, gate it.
You can use pthreads like Amy does, and it will run everywhere.
You could also use ACE or some similar toolkit.
// Here is something for process times under WIN32:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winperf.h>
#include <Psapi.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <errno.h>
#ifndef ENODATA
#define ENODATA 61
#endif
#ifndef RUSAGE_SELF
#define RUSAGE_SELF 0
#endif
#ifndef RUSAGE_CHILDREN
#define RUSAGE_CHILDREN -1
#endif
#ifdef _MSC_VER
typedef __int64 longlong;
#else
typedef long long longlong;
#endif
typedef struct timeval {
long tv_sec;
long tv_usec;
} timeval;
typedef struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
long ru_maxrss; /* integral max resident set size */
long ru_ixrss; /* integral shared text memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims */
long ru_majflt; /* page faults */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* messages sent */
long ru_msgrcv; /* messages received */
long ru_nsignals;/* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary context switches */
} rusage;
/* The function GetPerformanceInfo() may or may not exist (e.g. Windows 2003 has it) in Psapi.dll */
typedef BOOL(*pfnGetPerformanceInfo) (PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb);
int getrusage(int who, struct rusage * usage)
{
HANDLE process_handle;
PROCESS_MEMORY_COUNTERS pmc;
FILETIME create_time,
exit_time,
kernel_time,
user_time;
size_t page_size = 8192;
PPERFORMANCE_INFORMATION PerformanceInformation = {0};
DWORD cb = 0;
HMODULE hm;
pfnGetPerformanceInfo fnGetPerformanceInfo = 0;
hm = GetModuleHandle("Psapi.DLL");
if (hm)
fnGetPerformanceInfo = (pfnGetPerformanceInfo) GetProcAddress(hm, "GetPerformanceInfo");
if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) {
errno = EINVAL;
return -1;
}
/* Win32 systems do not have a convenient call to enumerate child
* processes that I am aware of. */
if (who == RUSAGE_CHILDREN) {
errno = ENODATA;
return -1;
}
process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
/*
*
http://msdn.microsoft.com/library/defau ... us/dllproc
* /base/getprocesstimes.asp */
if (GetProcessTimes(process_handle, &create_time, &exit_time, &kernel_time, &user_time)) {
longlong u_time = (*(longlong *) & user_time);
longlong k_time = (*(longlong *) & kernel_time);
/* The units returned by GetProcessTimes are 100 nanoseconds */
usage->ru_utime.tv_sec = (long) (u_time / 10000000);
usage->ru_stime.tv_sec = (long) (k_time / 10000000);
usage->ru_utime.tv_usec = (long) (u_time % 10000000);
usage->ru_stime.tv_usec = (long) (k_time % 10000000);
} else {
/* * Probably a permissions problem */
if (hm)
FreeLibrary(hm);
CloseHandle(process_handle);
errno = EACCES;
return -1;
}
if (fnGetPerformanceInfo && fnGetPerformanceInfo(PerformanceInformation, cb)) {
/* If the call fails, we will use an estimate of 8K per page. Else: */
page_size = PerformanceInformation->PageSize;
}
if (GetProcessMemoryInfo(process_handle, &pmc, sizeof(pmc))) {
usage->ru_maxrss = (DWORD) (pmc.WorkingSetSize / page_size);
usage->ru_majflt = pmc.PageFaultCount;
} else {
/* * Probably a permissions problem */
if (hm)
FreeLibrary(hm);
CloseHandle(process_handle);
errno = EACCES;
return -1;
}
if (hm)
FreeLibrary(hm);
CloseHandle(process_handle);
return 0;
}
typedef struct tms {
FILETIME tms_utime;
FILETIME tms_stime;
FILETIME tms_cutime;
FILETIME tms_cstime;
} tms;
longlong
times(struct tms * timebuf)
{
longlong user;
longlong kernel;
longlong dummy;
if (GetProcessTimes(GetCurrentProcess(), &dummy, &dummy,
&kernel, &user)) {
timebuf->tms_utime = (*(longlong *) &user);
timebuf->tms_stime = (*(longlong *) &kernel);
timebuf->tms_cutime = 0;
timebuf->tms_cstime = 0;
} else {
/* That failed - e.g. Win95 fallback to clock() */
clock_t t = clock();
timebuf->tms_utime = t;
timebuf->tms_stime = 0;
timebuf->tms_cutime = 0;
timebuf->tms_cstime = 0;
}
return timebuf->tms_utime ;
}
#ifdef UNIT_TEST
#include <time.h>
int main(void)
{
size_t i;
rusage ruse;
int r;
double cps_inv = 1.0 / CLOCKS_PER_SEC;
clock_t start,
end;
start = clock();
while ((clock() - start) * cps_inv < 1.0 && i++ < 1000000000 /* clock() can wrap */ )
r = rand();
Sleep(1000); /* We want wall time to be greater than
* process time to ensure it is working OK. */
getrusage(RUSAGE_SELF, &ruse);
printf("rusage user: %ld.%ld system: %ld.%ld\n",
ruse.ru_utime.tv_sec,
ruse.ru_utime.tv_usec,
ruse.ru_stime.tv_sec,
ruse.ru_stime.tv_usec);
return 0;
}
#endif