This guys purpose is to emulate a task switch that occurs when a timer event is fired.
So I have this code below that is my timer handler:
Code: Select all
irq0:
pusha ;Push all standard registers
push ds ;Push segment d
push es ;Push segmetn e
push fs ; ''
push gs ; ''
mov eax, 0x10 ;Get kernel data segment
mov ds, eax ;Put it in the data segment registers
mov es, eax
mov fs, eax
mov gs, eax
push esp ;Push pointer to all the stuff we just pushed
call TaskSwitch ;Call C code
mov esp, eax ;Replace the stack with what the C code gave us
mov al, 0x20 ;Port number AND command number to Acknowledge IRQ
out 0x20, al ;Acknowledge IRQ, so we keep getting interrupts
pop gs ;Put the data segments back
pop fs
pop es
pop ds
popa ;Put the standard registers back
;We didn't push an error code or IRQ number, so we don't have to edit esp now
iret ;Interrupt-Return
Code: Select all
typedef struct{ //Simple structure for a thread
unsigned int esp0; //Stack for kernel
unsigned int esp3; //Stack for process
unsigned long thread_id;
} Thread;
typedef struct _ThreadQueue ThreadQueue;
struct _ThreadQueue
{
ThreadQueue *prev;
ThreadQueue *next;
Thread *thread;
};
ThreadQueue *ReadyQueue;
unsigned int TaskSwitch(unsigned int OldEsp)
{
OSTicks++;
ThreadQueue *exec,*m_blk;
exec = ReadyQueue;
//First time into task switcher... the OldEsp is Thrown Away (Old kernel thread)
if (CurrentTask == -1)
{
CurrentTask = ReadyQueue->thread->thread_id;
return ReadyQueue->thread->esp0;
}
//If there is only one task to switch
if (ReadyQueue->next == 0)
{
ReadyQueue->thread->esp0 = OldEsp;
CurrentTask = ReadyQueue->thread->thread_id;
return ReadyQueue->thread->esp0;
}
//This case is for > 1 Thread
ReadyQueue = ReadyQueue->next;
for (m_blk = ReadyQueue; m_blk != 0; m_blk = m_blk->next)
{
if (m_blk->thread->thread_id == CurrentTask)
{
m_blk->thread->esp0 = OldEsp;
}
if (m_blk->next == 0)
{
m_blk->next = exec;
exec->prev = m_blk;
exec->next = 0;
}
}
CurrentTask = exec->thread->thread_id;
return exec->thread->esp0;
}
I tried an obvious
Code: Select all
extern TaskSwitch
YieldThread:
pusha ;Push all standard registers
push ds ;Push segment d
push es ;Push segmetn e
push fs ; ''
push gs ; ''
mov eax, 0x10 ;Get kernel data segment
mov ds, eax ;Put it in the data segment registers
mov es, eax
mov fs, eax
mov gs, eax
push esp ;Push pointer to all the stuff we just pushed
call TaskSwitch ;Call C code
mov esp, eax ;Replace the stack with what the C code gave us
pop gs ;Put the data segments back
pop fs
pop es
pop ds
popa ;Put the standard registers back
iret
;iret ;Interrupt-Return
And I am not really shore where to go from here...
Thanks,
Rich