To clear up stuff about RDTSC, he's what I just hacked up in zealos, it's
based on the .18 patch to do the same thing... My question is, how
would/should plex handle this?
I get loopsPerMs equal to 27 on this K5 box, whereas using the conventinal
method, I would get a value of about 99 million cycles per-second.
The way I think plex should handle this is work out the ammount of time in
between RDTSC calls, and then multiply that by the speed of the current
box or whatever...
--
Mark Zealey (aka JALH on irc.openprojects.net: #zealos and many more)
[EMAIL PROTECTED]
[EMAIL PROTECTED]
[EMAIL PROTECTED]
UL++++$ (GCM/GCS/GS/GM)GUG! dpu? s-:-@ a15! C+++>$ P++$>+++@ L+++>+++++$
!E---? W+++>$ N++@>+ o->+ w--- !M--? !V--? PS- PE--@ !PGP----? r++
!t---?@ !X---? !R- b+ !DI---? e->+++++ h+++*! y-
(www.geekcode.com)
// delay.c
/*
* Copyright (C) 02/08/2000 Mark Zealey ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307,
*
* This file was added to the ZealOS project on 02/08/2000 at 12:01:12 by Mark
* Zealey
*/
/* Notes/Changes:
* OK, the way we caliberate the delay loop is like this:
* 1) Find a rough value
* 2) go back down that xor'ing a mask to get the presice value
* Simple eh?
* This is quite like how linux does it except it's a bit shorter and a bit
* quicker.
*
* Step 1:
* We set an initial delay (of 1) to caliberate with. This then
* gets shifted up each time, till the loop is slower than 1000 Hz. It then
* shifts it back one.
* Step 2:
* A mask is applied (1 bit) and is rippled up till it's faster than 1000Hz
* as before, it's then shifted right by 1 and perminantly applied.
*
*/
#include <common.h>
#include <delay.h>
#include <desc.h>
#include <8259.h>
#include <printk.h>
#include <stdio.h>
#include <pit.h>
#include <asm_commands.h>
static volatile uchar tick = 0;
/* If we're on a 586 or greater (w/ RDTSC), the following value is in cycles per
* second. Otherwise, we just caliberate to the milisecond */
ulong loopsPerMs = 1;
/* Ugly kludge for a Us delay on non-RDTSC processors */
#if !(defined(__i386__) && (PROCESSOR >= 5))
ulong loopsPerUs;
#endif
handleInt(delayISR)
{
tick++;
}
// Calaberates the delay. This is a bogomips value :)
__uint8 delayInit()
{
ulong mask;
#if !(defined(__i386__) && (PROCESSOR >= 5))
__uint8 count = 32;
#endif
DPRINT("Caliberating delay loop: ");
// Set the PIT to 1000 interrupts a second.
pitSet(1000, 0);
// We add a handler to IRQ 0 (PIT).
addHandler(0, delayISR, 1);
do {
#if !(defined(__i386__) && (PROCESSOR >= 5))
if(!--count) // If we're about to overflow
break;
#endif
loopsPerMs <<= 1; // * 2
tick = 0;
while(!tick) /* Wait */; // Wait for the next tick
sleep(1); // (tick==1)
} while(tick == 1);
#if !(defined(__i386__) && (PROCESSOR >= 5))
if(!count) {
printk("Your processor is just too fast (and too old) :/\n");
return FALSE;
}
#endif
loopsPerMs >>= 1; // back 1
mask = loopsPerMs; // set the mask to us
while(mask) { // do fine calaberation
mask >>= 1; // move the mask bit
loopsPerMs |= mask; // Apply the mask
tick = 0;
while(!tick) /* Wait */;
sleep(1); // (tick now = 1)
if(tick != 1) // If a tick has passed
loopsPerMs ^= mask; // remove it
}
#if !(defined(__i386__) && (PROCESSOR >= 5))
loopsPerUs = loopsPerMs / 1000; // Ugly hack :/
#endif
delHandler(0, delayISR);
pitSet(Hz, 0); // Reset the Pic
printk("Done! :)\n");
DPRINT("Now delaying 10 seconds to varify that the value is correct\n");
sleep(10000);
DPRINT("10 Secs is up. Let's get on wit it! :)\n"); // Test :)
return TRUE;
}
#if defined(__i386__) && (PROCESSOR >= 5)
// delays for about 1Us
void __1sleepRdtsc()
{
__uint32 a, b, c; // a is not actually used
rdtsc(a,b);
do {
rdtsc(a,c);
} while((c-b) < loopsPerMs); // Really Us
}
void usleep(ulong us)
{
for(;us;us--)
__1sleepRdtsc();
}
void sleep(ulong ms)
{
for(;ms;ms--)
usleep(1000);
}
#else
// delays for x ms
void sleep(ulong ms)
{
ulong t;
for(;ms;ms--)
for(t=loopsPerMs;t;t--)
/* Wait */;
}
// delays for x us
void usleep(ulong us)
{
ulong t;
for(;us;us--)
for(t=loopsPerUs;t;t--)
/* Wait */;
}
#endif
// END