Basic VM and other minor improvements.

Not complete, probably not fully debugged or optimized.
This commit is contained in:
Ben Gras
2008-11-19 12:26:10 +00:00
parent c888305e21
commit c078ec0331
273 changed files with 10814 additions and 4305 deletions

View File

@@ -10,20 +10,31 @@
#include "sysutil.h"
#define CALIBRATE_TICKS (HZ/5)
#define CALIBRATE_TICKS(h) ((h)/5)
#define MICROHZ 1000000 /* number of micros per second */
#define MICROSPERTICK (MICROHZ/HZ) /* number of micros per HZ tick */
#define MICROSPERTICK(h) (MICROHZ/(h)) /* number of micros per HZ tick */
static u32_t calib_tsc;
#define CALIBRATE \
if(!calibrated) { \
int r; \
if((r=micro_delay_calibrate()) != OK) \
panic(__FILE__, "micro_delay: calibrate failed\n", r); \
}
static u32_t calib_tsc, Hz = 0;
static int calibrated = 0;
int
micro_delay_calibrate(void)
{
u64_t start, end, diff, hz;
u64_t start, end, diff;
struct tms tms;
unsigned long t = 0;
/* Get HZ. */
if(sys_getinfo(GET_HZ, &Hz, sizeof(Hz), 0, 0) != OK)
Hz = HZ;
/* Wait for clock to tick. */
while(!t || (t == times(&tms)))
t = times(&tms);
@@ -34,7 +45,7 @@ micro_delay_calibrate(void)
* this using the TSC.
*/
read_tsc_64(&start);
while(times(&tms) < t+CALIBRATE_TICKS) ;
while(times(&tms) < t+CALIBRATE_TICKS(Hz)) ;
read_tsc_64(&end);
diff = sub64(end, start);
@@ -43,10 +54,12 @@ micro_delay_calibrate(void)
"micro_delay_calibrate: CALIBRATE_TICKS too high "
"for TSC frequency\n", NO_NUM);
calib_tsc = ex64lo(diff);
#if 0
printf("micro_delay_calibrate: "
"%lu cycles/%d ticks of %d Hz; %lu cycles/s\n",
calib_tsc, CALIBRATE_TICKS, HZ,
div64u(mul64u(calib_tsc, HZ), CALIBRATE_TICKS));
calib_tsc, CALIBRATE_TICKS(Hz), Hz,
div64u(mul64u(calib_tsc, Hz), CALIBRATE_TICKS(Hz)));
#endif
calibrated = 1;
return OK;
@@ -60,17 +73,11 @@ micro_delay(u32_t micros)
/* Start of delay. */
read_tsc_64(&now);
/* We have to be calibrated. */
if(!calibrated) {
int r;
printf("micro_delay: calibrating\n");
if((r=micro_delay_calibrate()) != OK)
panic(__FILE__, "micro_delay: calibrate failed\n", r);
}
CALIBRATE;
/* We have to know when to end the delay. */
end = add64u(now, div64u(mul64u(calib_tsc,
micros * HZ / CALIBRATE_TICKS), MICROHZ));
micros * Hz / CALIBRATE_TICKS(Hz)), MICROHZ));
/* If we have to wait for at least one HZ tick, use the regular
* tickdelay first. Round downwards on purpose, so the average
@@ -78,8 +85,8 @@ micro_delay(u32_t micros)
* we call tickdelay). We can correct for both overhead of tickdelay
* itself and the short wait in the busywait later.
*/
if(micros >= MICROSPERTICK)
tickdelay(micros*HZ/MICROHZ);
if(micros >= MICROSPERTICK(Hz))
tickdelay(micros*Hz/MICROHZ);
/* Wait (the rest) of the delay time using busywait. */
while(cmp64(now, end) < 0)
@@ -87,3 +94,4 @@ micro_delay(u32_t micros)
return OK;
}