#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//#include <sys/time.h>
#include <time.h>
//#include <unistd.h>
//#include <sys/types.h>
#include <unistd.h>
#define __USE_GNU 1
#include <sched.h>
typedef unsigned char bool;


#if defined(__i386__)

static __inline__ unsigned long long read_rdtsc(void)
{
  unsigned long long int x;
     __asm__ ("cpuid\n");
     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
     return x;
}
#elif defined(__x86_64__)


static __inline__ unsigned long long read_rdtsc(void)
{
  unsigned hi, lo;
  __asm__ ("cpuid\n");
  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
  return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

#elif defined(__powerpc__)


static __inline__ unsigned long long read_rdtsc(void)
{
  unsigned long long int result=0;
  unsigned long int upper, lower,tmp;
  __asm__ ("cpuid\n");
  __asm__ volatile(
                "0:                  \n"
                "\tmftbu   %0           \n"
                "\tmftb    %1           \n"
                "\tmftbu   %2           \n"
                "\tcmpw    %2,%0        \n"
                "\tbne     0b         \n"
                : "=r"(upper),"=r"(lower),"=r"(tmp)
                );
  result = upper;
  result = result<<32;
  result = result|lower;

  return(result);
}

#endif


int main(int argc, char **argv){
	//unsigned long mask = 1;
	//unsigned int len = sizeof(mask);

	//bool value;
	//struct timespec ts;
	//long double te0, te1, te2, te3, te4, te5;
	//long double calc1, calc2;
	unsigned long long base;
	//struct timespec starttime, endtime;
	//int ret_val, ret_val2;

	//double last_te0, last_te1, last_te2;
	//unsigned int increment_offset = 0;
	//unsigned int increment_bytes = 4096;
	//unsigned char increment_count = 0;


cpu_set_t  mask;

CPU_ZERO(&mask);
CPU_SET(0, &mask);

//CPU_SET(2, &mask);
//sched_setaffinity(0, sizeof(mask), &mask);


if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
    perror("sched_setaffinity");
}
	double CPU_MHZ = 1;



	unsigned long long first_clock;
	//unsigned long long last_clock;




#ifdef __linux__
	FILE* fp;
	char buf[256];
	char mhz_buf[16];
	int count = 0;
	int found = 0;

        if( ( fp = fopen( "/proc/cpuinfo", "r" ) ) == NULL ) {
                fprintf( stderr, "Error opening /proc/cpuinfo !\n" );
                exit( 1 );
        }
	//cpu MHz		: 3208.243
        while( fgets(buf, sizeof(buf), fp) != NULL)
        {
		if (buf[count] == 'c'){
			if (buf[count+1] == 'p'){
				if (buf[count+4] == 'M'){
					if (buf[count+5] == 'H'){
						for(count=0; count<16; count++){
							mhz_buf[count]='\0';
						}
						found=1;
						//starting at 10 untill end
						for(count = 10; buf[count] != '\n'; count++){
							mhz_buf[count-10]=buf[count];
						}
					}
				}
			}
		}
	}
	if(found){
		CPU_MHZ=atof(mhz_buf);
	}
	fclose( fp );
	//free(buf);
	//free(mhz_buf);
	printf("CPU frequency(/proc/cpuinfo): %lf\n", CPU_MHZ);
	
#endif
	//if(CPU_MHZ == 1){
	//	printf("Warning: your platform is not supported yet, numbers will be inaccurate!\n");
	//	CPU_MHZ = 3000;
	//}

	first_clock = read_rdtsc();
	sleep(1);
	base = (long long)(read_rdtsc() - first_clock);
	printf("estimated cpu freq(rdtsc): %lfMHz\n", (double)base/1000/1000);
	//printf("freq (dmidecode)");
	system("echo 'freq (dmidecode)' && dmidecode |grep Current|head -1");
	return 0;
}
