Page 1 of 2
function like Delay(ms); in Pascal
Posted: Wed Feb 21, 2007 2:24 pm
by Cmaranec
I am really beginer in OSDev.
Can you help me with function like Delay(ms); in Pascal or Sleep(ms); in Win API ? I have timer, but i don't know how to make "slowing function". Can you help me please?
Posted: Wed Feb 21, 2007 2:31 pm
by uglyoldbob
For this I programmed the timer (IRQ 0) to fire ~1000 times a second.
Delay(unsigned int milliseconds) is called from C code
hope this helps
timer dd 0
irqM0:
push ax
inc dword [timer]
;manual EOI before the interrupt has ended
mov al, 0x20
out 0x20, al
pop ax
iret
[global Delay]
Delay: ;delays for some number of irq0 firings (each of which are about 1 millisecond)
push eax
push ebx
mov eax, [timer]
add eax, [esp + 12] ;eax = delay + time
.wait
mov ebx, [timer]
cmp eax, ebx
jg .wait
pop ebx
pop eax
ret
ehh..
Posted: Wed Feb 21, 2007 2:41 pm
by Cmaranec
Can I do it in C++ ?
Posted: Wed Feb 21, 2007 2:51 pm
by uglyoldbob
Yes it will work with C++ code, but you will want to change the declarator in the C++ code to:
extern "C" void Delay(unsigned int milliseconds);
This should avoid name mangling.
Posted: Wed Feb 21, 2007 4:27 pm
by Tyler
How would this be done if the Scheduler was relying on the PIT?
Posted: Wed Feb 21, 2007 5:20 pm
by uglyoldbob
BogoMips? Take a quick spin around google for it. It is a calculation of how fast your computer can do "nothing" and can ppossibly be used for timing loops.
Posted: Wed Feb 21, 2007 10:33 pm
by Tyler
uglyoldbob wrote:BogoMips? Take a quick spin around google for it. It is a calculation of how fast your computer can do "nothing" and can ppossibly be used for timing loops.
No i mean.. what does the timing for a delay function if it cant get access to a PIT? For example in user mode code where the kernel cant provide the service because the kernel uses the PIT for sceduling...
Posted: Wed Feb 21, 2007 11:55 pm
by uglyoldbob
You would probably have to use the RTC clock for that (which isn't supported on all hardware, can't seem to remember what doesn't support it, probably old stuff). Or you could introduce a method into your scheduler that delays a process/thread for a minimum of x timer ticks.
//add an item for each process that says (earliest time to execute)
//pretend earlyTime is the variable for the process/thread
earlyTime dd 0
Delay
mov eax, [ticks]
mov [earlyTime], eax
(switch to another task)
ret
EXAMPLE
ticks dd 0
irq0:
inc dword [ticks]
//bla bla scheduler code
//found a process/thread to switch to maybe?
mov eax, earlyTime
cmp eax, [ticks]
if (eax < [ticks])
DONT do this thread/process
This might be the easiest, but you'll probably have to use software task switching instead of hardware switching becuase of the added information for each task.
Thaks
Posted: Thu Feb 22, 2007 3:16 am
by Cmaranec
Thank you.
hm...
Posted: Thu Feb 22, 2007 3:34 am
by Cmaranec
Now, the linker giving this:
main.o(.text+0x1ff):main.c: undefined reference to `_Delay'
i wrote "extern void Delay(unsigned int cas);" into system.h included from all .C files of my OS.
i wrote "Delay(2000);" into main.c (for wait 2 seconds)
i wrote your code for Delay: into start.asm when i setting up all IRQ's.
i wrote your code for irqM0: into start.asm into setting of IRQ0
Posted: Thu Feb 22, 2007 4:44 am
by AJ
Hi - a couple of things:
1) If you want to access your assembly routine from C, you need to prefix the assembly label with an underscore (ie _Delay, rather than Delay).
2) Can the linker see all of your object files and are they all in a supported format?
3) Have you put a 'global _Delay' somewhere in your assembly code?
HTH,
Adam
Posted: Thu Feb 22, 2007 5:39 am
by inflater
If you have GDT.INC (or something) accessible by your OS kernel, you can switch to real mode -
and use INT15,AH=86h function Wait.
CX*65535 and DX is the number of microseconds to wait.
The precision for this function is 977 microseconds.
Then you can switch to protected mode by loading GDT, IDT and other necessary data to stack and setting the first bit of CR0 to 1.
But beware - if this function is used very frequently in your OS - your minimal system requirements may be higher than a regular 80386 - switching to real mode from PMode just for delay function and hopping back to PM can be on older machines slow. But it is a delay procedure, so who cares?
Posted: Thu Feb 22, 2007 8:03 am
by Brendan
Hi,
inflater wrote:But beware - if this function is used very frequently in your OS - your minimal system requirements may be higher than a regular 80386 - switching to real mode from PMode just for delay function and hopping back to PM can be on older machines slow. But it is a delay procedure, so who cares?
I'd guess anyone trying to write protected mode IRQ handlers would be deeply disturbed by this - worst case IRQ latency measured in days....
Cheers,
Brendan
Posted: Sun Feb 25, 2007 11:39 am
by Tyler
Hey
I recently implemented a delay function in my native library... for the sake of it. But it causes serious problems the way i am doing it. Does anyone know how it is done by an operatin system like linux? Do they use the PIT and time the system with APIC or do they simply check the RTC during kernel mode access?
Posted: Sun Feb 25, 2007 12:51 pm
by frank
Tyler wrote:Hey
I recently implemented a delay function in my native library... for the sake of it. But it causes serious problems the way i am doing it. Does anyone know how it is done by an operatin system like linux? Do they use the PIT and time the system with APIC or do they simply check the RTC during kernel mode access?
I don't know how linux does it however, I can tell you how my delay function works. When you call the delay function it passes on the delay count to the scheduler and tells the scheduler not to wake the task up before this delay has passed. Of course that is how I do it, and I'm sure that this is not the only way.