Archived

This topic is now archived and is closed to further replies.

remi

mircosecond

Recommended Posts

Hi all! I would like to know if it''s a function like Sleep() but that can make the program stop just for some mircoseconds. The error should not be more than 2 microseconds. I believe that with faster CPU with have nowadays, it should not be very hard to achieve that, but i was unable to find such a function. Any help is welcome(it''s urgent plz).

Share this post


Link to post
Share on other sites
Not really. you can do with with some RealTime OS''s, but not with windows (afaik) and not even with linux without some "make linux a RTOS" patch.

its not CPU, really, its clock rate. Most OS''s keep the clock rate down real around 100hz (linux 2.6 uses 1000, i believe) because the higher you go, the more overhead is involved.

problem is, this low you can''t get resolutions of 2 microseconds easily.

Share this post


Link to post
Share on other sites
no, it is not possible to achieve that with any normal desktop OS ... period.

The reason is simple, the OSes are pre-emptive multi-tasking, with a scheduler whose job it is to maintain fair resource allocation for competing tasks, without undue reasource waste ... the absolute BEST multithreaded OS for the desktop was BeOS, which had a scheduler with 1ms (millisecond, not microsecond) accuracy, this means that in BeOS, if your thread has sufficiently high priority, the sleep function is usually acurate to +- 0.5 ms. Traditionally, windows 32, I know windows 95 and 98 specifically, had a scheduler that was only accurate to the 18.2 FPS timer, aka 55 ms. This was so attrocious as to be completely useless for modern games ... so people did not use it.

An OS could, and some real time OSes due, give timer and wakeup accuracy in the 2-4 um (microsecond) range, but this is the best I have seen to date, and only realy works when there are not many important system threads competing to draw the screen, manage resources, etc ... these OSes usually do not even run a graphical desktop, because they are used for network switching fabric, audio/video feed routing, etc ... normal OSes do not drop to this level, because it is completely inconsistent with trying to acheive efficient use of a processor, on a system which takes more than 1um per normal operation ...

think for a second, 1 um means 1 MHz, if the processor is running at say 1GHz (which is 3 times lower than the top end, and about 3 times higher than the current bottom end), that only gives you 1000 clock cycles to use for all other threads before returning to the current one ... remmber that task switching uses a fair number of clock cycles, as do the operations actually performed by the other threads ... also, the memory itself is more likely running around 266 MHz, 64 bit wide, not couting access latency ... which gives you only the ability to read and write about 500 integers per time slice, maximum ... the real world is MUCH MUCH less (my guess is more like 50-100).

Basically, an OS which tried to achieve such precision would only be suitable with 2 conditions, 1 - the application and facilities used by it (including all needed OS functions) almost completely fits inside cache memory (at least during any given segment of operation), 2 - there are no more than 1-3 threads of any primary importance running in the system, and not more than 5-9 of any significance whatsoever ... else the thrashing would destoy performance.

This is largely speculation on my part, as I am an application programmer, not a system or driver programmer, but I did work for 2+ years on an embedded game platform, and then 2 years at an audio processing company (which used BeOS, many threads, and had significant latency requirements). Please feel free to correct anything I have wrong, I would like to learn more about the current state of things is this area.

Share this post


Link to post
Share on other sites
because the timers are updated by the clock ship, which is set to a several millisecond accuracy.

Unless there are "high resolution timers" that do some nifty timing operations with CPU cycles.... which would vary a lot, since such things are inexact science last time i checked.

and still, your process can still be task switch in the middle of a busy wait. suddenly its 100 milliseconds later...

Share this post


Link to post
Share on other sites
After reading this post , i tried QueryPerformanceFrequency() and QueryPerformanceCounter(), they seem really accurate(at least better GetTickCount()), but still not accurate enough as far as the microsecond is concerned.

I still believe that with the faster CPUs we have now, it's possible to achieve that task, why?
Not so sure, but take the example of the serial commucation(COM port), it can work at a speed of 128 000Baud = 128 000bit/s, so 1bit needs around 7.9microseconds to be sent!



[edited by - remi on July 26, 2003 10:15:18 PM]

Share this post


Link to post
Share on other sites
>> Why not do a busy wait with a high resolution timer?
> because the timers are updated by the clock ship, which is set to a several millisecond accuracy.
The CTC chip is a 1.193 MHZ 16 bit counter. "accuracy" is a divisor that determines how often an interrupt is triggered, in which Windows updates its timer. The point? Windows timing functions (excepting QPC) are not high-resolution timers

> Unless there are "high resolution timers" that do some nifty timing operations with CPU cycles.... which would vary a lot, since such things are inexact science last time i checked. <
rdtsc. The cycle counter does indeed jitter a bit (CPU clock crystal ain''t all too good), but doesn''t matter due to the awesome resolution.

> and still, your process can still be task switch in the middle of a busy wait. suddenly its 100 milliseconds later... <
Harr, not if you''re running at priority 31 >:]

Share this post


Link to post
Share on other sites
check out the rdtsc instruction, it lets you measure clock cycles. its tricky to get the clock frequency though, and unreliable because of modern CPUs changing frequencies in laptops and such.

Share this post


Link to post
Share on other sites
Can you be more specific about why you need to wait for 2 microseconds? Perhaps there is a much better solution to your particular problem.

Share this post


Link to post
Share on other sites
I think i have been specific enough!

The project i''m working on has to do with the hardware(LPT port,....), and letting the chip connected to the PC sleep for milliseconds would be a pretty good waste of speed!

Share this post


Link to post
Share on other sites
As has already been stated in this thread getting a program to pause for 2 microseconds (even measure it accurately) is extremely hard and just about impossible on OSs such as Windows.

You say you need to do this because of the speed the com and LPT port work at. But you don''t send data to these ports 1 bit at a time perfectly synchronized. I''m not 100% sure on this, but these ports will have a controller chip that will have a little memory buffer. Your program sends its data to that memory buffer and the controller chip handles sending it through the com or LPT port.

Share this post


Link to post
Share on other sites
quote:
Original post by Monder
say you need to do this because of the speed the com and LPT port work at.


Sorry but i didn''t say that!
I said i need to do that because of the speed of the CHIP that is going TO BE CONNECTED to the LPT port...

Share this post


Link to post
Share on other sites
What chip? A chip on an externel H/W device? In that case it will have to be fast enough to recieve data and as it won''t have a preepmtive multi-tasking OS on it, shouldn''t be that hard to code.

Share this post


Link to post
Share on other sites
sending data should be a matter of dumping it to the ports and letting the hardware deal with it.
Connected to the ports the hardware should have enuff logic that it can sync with the data and buffer it itself before sending it on for processing by the chip (linking a series of flip-flops as a D-series data-latch (my terminalogy is a bit rusty, been a few years since i did electronics) allows for the buffering/and or the serial->parrell conversion)

Then all you have to do is, on start up, sync the sending rate of the system in with the data-latches, then all you do is send the data and query when its gone and the port is ready for some more before sending the rest, busy looping the rest of the time doing a fast query on the correct ports.

Tada, with teh right hardware and software approuch no need to sleep() at all.

Share this post


Link to post
Share on other sites
quote:
Original post by remi
Hi all!
I would like to know if it's a function like Sleep() but that can make the program stop just for some mircoseconds. The error should not be more than 2 microseconds.

I believe that with faster CPU with have nowadays, it should not be very hard to achieve that, but i was unable to find such a function.

Any help is welcome(it's urgent plz).



I think what you want is this (from the top of my head but it should compile just fine):


#include <stdio.h>

inline unsigned int getcputime(void)
{
unsigned int store = 0;
__asm
{
RDTSC;
MOV store,eax;
}
return store;
}

int main(void)
{
unsigned int value1 = 0;
unsigned int value2 = 0;
value1 = getcputime();
value2 = getcputime();
printf("Value1:%x\n",value1);
printf("Value2:%x\n",value2);
return 0;
}


edit(add):

The high order is in EDX but since you only want the low part we can skip that. ;-)

If you are unsure then you can contact me at my forum (www.planetrift.com)
If you are unsure about a term in english feel free to write in mandarin.

hope this helps.


____________________________________________________________
Try RealityRift at www.planetrift.com
Feel free to comment, object, laugh at or agree to this. I won't engage in flaming because of what I have said.
I could be wrong or right but the ideas are mine.



[edited by - MichaelT on July 27, 2003 11:39:47 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by xaxa
what about unistd.h and nanosleep()?


Plz can u tell where to find "unistd.h"?
Accordinf to this page, it''s like "unistd.h" is for unix. But on this page, it''s like nanosleep() is also included inside "time.h", but it seems not to be the case(the code still fail to compile).

quote:
Original post by MichaelT I think what you want is this (from the top of my head but it should compile just fine)....


Thanx for ur code, it compiles and works fine, but i don''t really understand what it does. Would give a little explanation plz?

Share this post


Link to post
Share on other sites
quote:
Original post by LessBread
My understanding is that for best results, the instruction queue needs to be serialized before using the rdtsc instruction and that cpuid is typically used to achieve this. Assembly Gem 29.

And for what it's worth, some of the articles here might be useful to your endeavor: information.


Correct, *almost* but RDTSC is not a serializing instruction so mnemonics that are called >after< RDTSC may not get the right value anyway because they *might* run *before* the new value for EAX has arrived, in which case the CPU fails and have to try again. My sample was simplified agreed, but calling CPUID is not the answer. What you need to do is to make sure that EAX is changed. If it is unchanged you wait in a loop until you get a new value. However it should be noted that the first function I wrote hardly ever fails but when it does the difference is more than doubled. Anyway, if you want to make sure it is changed you can do as I have done in 'getcputime2'. Using CPUID is much too slow. Comparing leads to an almost perfectly stable rate and still is much faster than using CPUID.

Here is a new example, displaying all three methods:


#include <stdio.h>

inline unsigned int getcputime(void)
{
static unsigned int store = 0;
__asm
{
RDTSC;
MOV store,eax;
}
return store;
}

inline unsigned int getcputime2(void)
{
static unsigned int store = 0;
__asm
{
XOR eax,eax;
RDTSC;
go_back:;
cmp eax,0;
JZ go_back;
MOV store,eax;
}
return store;
}

inline unsigned int getcputime3(void)
{
static unsigned int store = 0;
__asm
{
CPUID
RDTSC;
MOV store,eax;
}
return store;
}

int main(void)
{
unsigned int value1 = 0;
unsigned int value2 = 0;

value1 = getcputime();
value2 = getcputime();
printf("Value1:%x\n",value1);
printf("Value2:%x\n",value2);
printf("Differ:%x\n",value2 - value1);

value1 = getcputime2();
value2 = getcputime2();
printf("Value1:%x\n",value1);
printf("Value2:%x\n",value2);
printf("Differ:%x\n",value2 - value1);

value1 = getcputime3();
value2 = getcputime3();
printf("Value1:%x\n",value1);
printf("Value2:%x\n",value2);
printf("Differ:%x\n",value2 - value1);

return 0;
}


By running this, you will notice that the CPUID versions is consistently slower than the loop version and the first version(much slower infact). The thing is that the changing of EAX is guaranteed. So we can loop back to the compare function until the new value arrives.

However, to use this as a high precision timer you also need a confirmed time to go with it. So calling TimeGetTime or other is essential. But once that is done, you can get extreme timing precision. There is one caveat here. A value can loop around because the EAX register only holds half of the bits. So there will be a miss every now and then depending on CPU model. You will have to make sure to properly handle that case.

Feel free to comment on any incorrect statements I might have. After all, it has been a few years since I really worked with assembler ;-)

I will also put this up on my site for reference.

____________________________________________________________
Try RealityRift at www.planetrift.com
Feel free to comment, object, laugh at or agree to this. I won't engage in flaming because of what I have said.
I could be wrong or right but the ideas are mine.



[edited by - MichaelT on July 27, 2003 6:59:59 PM]

[edited by - MichaelT on July 27, 2003 7:02:47 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Xai
no, it is not possible to achieve that with any normal desktop OS ... period.



Does Solaris not qualify as normal?

The problem is that is takes hardware to make this happen - a programmable counter/timer chip and an IRQ line. (It takes hardware to make it happen without significant overhead).

[edited by - Magmai Kai Holmlor on July 27, 2003 10:00:22 PM]

Share this post


Link to post
Share on other sites
quote:

I think i have been specific enough!


I doubt you''re working on a top secret military project here. As has already been said, you can realistically forget about doing this without a realtime OS, so without more specific information we really can''t help. Can you signal the hardware to delay? For example sending a command to fire a monostable?

Share this post


Link to post
Share on other sites
quote:
Original post by joanusdmentia
quote:

I think i have been specific enough!


I doubt you're working on a top secret military project here. As has already been said, you can realistically forget about doing this without a realtime OS, so without more specific information we really can't help. Can you signal the hardware to delay? For example sending a command to fire a monostable?



No, it's defenitely not a military project,nore a top secret one. I just hope the answer could help the others in their different projects, not just mine.

BTW: this could solve the problem, but it crashes all the time(may be because of the restrictions made on Xp/2000).





[edited by - remi on July 28, 2003 3:47:25 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by remi
quote:
Original post by joanusdmentia
quote:

I think i have been specific enough!


I doubt you're working on a top secret military project here. As has already been said, you can realistically forget about doing this without a realtime OS, so without more specific information we really can't help. Can you signal the hardware to delay? For example sending a command to fire a monostable?



No, it's defenitely not a military project,nore a top secret one. I just hope the answer could help the others in their different projects, not just mine.

[edited by - remi on July 28, 2003 3:47:25 AM]


Don't listen to him, of course you can be that precise.

try this:


#include <windows.h>
#pragma comment(lib,"winmm.lib")

#include <stdio.h>

__int64 large = 0;

inline void getcputime2(void)
{
static unsigned int store = 0; //we use static to avoid create/destruct

static unsigned int store2 = 0;

__asm
{
XOR eax,eax;
RDTSC;
go_back:;
cmp eax,0;
JZ go_back;
MOV store2,edx;
MOV store,eax;
}

large = (((__int64)store2)<<32) + store;

return;
}

int main(void)
{
getcputime2();

__int64 large2 = large;

DWORD start = timeGetTime();
DWORD end = start;

while((end - start)<1000)end = timeGetTime();

getcputime2();

printf("time = %li\n",end - start);
printf("cycles = %x\n",large - large2);

__int64 um = ((large - large2)/((end - start))/1000) << 1;

UINT low = (UINT)um;
UINT high = (UINT)(um>>32);
printf("cycles for 2 um = %x%x\n",high,low );

printf("Let us test this...\n");

getcputime2();

large2 = large;

um-=50; //for the extra time we do a run


while((large - large2)<um)getcputime2();

low = (UINT)large2;
high = (UINT)(large2>>32);
printf("cycles_start = %x%x\n",high,low);

low = (UINT)large;
high = (UINT)(large>>32);
printf("cycles_end = %x%x\n",high,low);

printf("cycles = %lx\n",large - large2);

printf("a fairly precise estimate\n");

return 0;
}


www.planetrift.com

I changed it to use __int64 instead.


[edited by - MichaelT on July 28, 2003 7:02:46 AM]

[edited by - MichaelT on July 28, 2003 7:13:49 AM]

Share this post


Link to post
Share on other sites
Why not simply do:

inline __int64 GetTicks()
{
__asm rdtsc
}

...instead of moving the value to a global? Some compilers will probably give a warning here, but you can avoid that with some fancy #pragma, which I can''t remember right now. VC.NET accepts it, in any case.


"For crying out loud, she has fishes coming out of her head on either side. How can you find this hot?!"

"If anyone sees a suspicious, camouflaged factory being carried across the desert, they should report it immediately."

Share this post


Link to post
Share on other sites
quote:
Original post by MichaelT
quote:
Original post by Valderman
Why not simply do:

inline __int64 GetTicks()
{
__asm rdtsc
}

...instead of moving the value to a global? Some compilers will probably give a warning here, but you can avoid that with some fancy #pragma, which I can''t remember right now. VC.NET accepts it, in any case.


"For crying out loud, she has fishes coming out of her head on either side. How can you find this hot?!"

"If anyone sees a suspicious, camouflaged factory being carried across the desert, they should report it immediately ."



Because RDTSC is a non serializing instruction. That means that other instructions can run even before the instruction has started. And the other way around, it may run before previous intructions have finished. I could ignore the global though.
____________________________________________________________
Try RealityRift at www.planetrift.com
Feel free to comment, object, laugh at or agree to this. I won''t engage in flaming because of what I have said.
I could be wrong or right but the ideas are mine.






____________________________________________________________
Try RealityRift at www.planetrift.com
Feel free to comment, object, laugh at or agree to this. I won''t engage in flaming because of what I have said.
I could be wrong or right but the ideas are mine.

Share this post


Link to post
Share on other sites