Пример #1
0
// get current time, without recalibration
__forceinline ULONGLONG gethectonanotime_norecal(void) {
	ULONGLONG curtsc;

	// get the timestamp right up front
	curtsc = gettsc();
	return hectonanotime_of_tsc(curtsc);
}
Пример #2
0
/* We have 3 entropy sources:
 * - random values given in auxv at startup (32 bytes)
 * - /dev/urandom
 * - rdtsc + gettimeofday
 */
static void reseed_pool(Elf_auxv_t *auxv){
	SHA256_CTX ctx;
	int i;
	int fd;
	uint8_t buffer[32];
	uint32_t tsc[2];

	SHA256_Init(&ctx);

	gettsc(tsc);
	SHA256_Update(&ctx, tsc, sizeof(tsc));
#ifdef AT_RANDOM
	for (i=0; auxv[i].a_type != AT_NULL; ++i){
		switch(auxv[i].a_type){
		case AT_RANDOM:
			/* 16 random bytes */
			SHA256_Update(&ctx, (void *)auxv[i].a_un.a_val, 16);
			break;
		}
	}
#endif
	gettsc(tsc);
	SHA256_Update(&ctx, tsc, sizeof(tsc));

	fd = open("/dev/urandom", O_RDONLY);
	if(fd >= 0){
		read(fd, buffer, sizeof(buffer));
		SHA256_Update(&ctx, buffer, sizeof(buffer));
		close(fd);
	} else {
		fd = open("/dev/random", O_RDONLY);
		if (fd >= 0){
			/* /dev/random is more expensive to use */
			read(fd, buffer, 8);
			SHA256_Update(&ctx, buffer, 8);
			close(fd);
		}
	}
	for (i=0;i<32;++i){
		getpid();
		gettsc(tsc);
		SHA256_Update(&ctx, tsc, sizeof(tsc));
	}
	SHA256_Final(entropy_pool, &ctx);
}
Пример #3
0
// get time of call, possibly recalibrating before returning
__forceinline ULONGLONG gethectonanotime_first(void) {
	ULONGLONG curtsc = gettsc();
	ULONGLONG now = hectonanotime_of_tsc(curtsc);
	if ((lastrecal == 0) || (now - lastrecal) > recalinterval) {
		recalibrate();
		now = hectonanotime_of_tsc(curtsc);
	}
	return now;
}
Пример #4
0
void recalibrate(void) {
	int i;

	ULONGLONG basetscs[nreps];  // basetsc for each round
	ULONGLONG basests[nreps];   // basest for each round

        char buf[100] = "0";

	// read calibration
	HKEY key;
	DWORD cbData;
	RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\NetSem\\TTHEE",0,KEY_READ,&key);
	cbData = sizeof(tscfreq);
	RegQueryValueEx(key,"tscfreq",NULL,NULL,(BYTE *)&tscfreq,&cbData);
	cbData = sizeof(tscsd);
	RegQueryValueEx(key,"tscsd",NULL,NULL,(BYTE *)&tscsd,&cbData);
	// double error = double(tscsd) / double(tscfreq);
        cbData = sizeof(buf)-1;
	RegQueryValueEx(key,"ugly_hack_offset",NULL,NULL,(BYTE *)buf,&cbData);
        buf[cbData] = '\0';
        ugly_hack_offset = _atoi64(buf);

	// get base times
	for (i=0; i<nreps; i++) {
		FILETIME baseft;
		Sleep(5);  // to be sure we're on a tick boundary
		basetscs[i] = gettsc();  // get this first because it changes very fast
		GetSystemTimeAsFileTime(&baseft);  // no rush; we have 1/64 sec to read this before it changes
		basests[i] = ((ULONGLONG)baseft.dwHighDateTime)<<32 | ((ULONGLONG)baseft.dwLowDateTime);
	}

	basetsc = basetscs[nreps-1];
	/* Now: we want to know the correct basest for the latest basetsc.  Each measurement can be
	   extrapolated to give us a basest for the latest basetsc.  But if there was a delay between the
	   tick and our process being scheduled in a particular round, this will show up as the basetsc
	   being high, a.k.a., the basest being low.  Thus, we take the highest computed basest. */
	basest = basests[nreps-1];
	for (i=0; i<nreps; i++) {
		ULONGLONG basestx = basests[i] + (10000000 * (basetscs[nreps-1] - basetscs[i])) / tscfreq;
			// don't worry about overflow; at 500MHz (glia) it won't overflow until just over an hour
		if (basestx > basest) {
			basest = basestx;
		}
	}

        basest -= ugly_hack_offset;   // apply the hack offset.

	lastrecal = basest;  // we just recalibrated.
}