i decided to open a new post for this, as its not really got to do with the original problem of the old post any more
still stuck with hardware multitasking
i have my 2 tasks, task1 and task2
they just run in a loop:
Code: Select all
procedure task1;
begin task1;
forever
inc(somevariable);
endfor;
end task1;
-kernel executes hlt with interrupts set
-clock occurs, sets backlink of kernel tss to task1, sets busy flag for task1, sets nt flag in flags register so that when interrupt returns:
-task1 executes
-clock occurs, sets backlink of task1 tss to task1, sets busy flag for task2, sets nt flag in flags register so that when interrupt returns:
-task2 executes
-clock occurs, sets backlink of task2 tss to task1, sets busy flag for task1, sets nt flag in flags register so that when interrupt returns:
-task1 executes
-and so on, task1 and task2 alternating
the problem is i get only as far as to task 2.
once task2 executes for the first time and gets interrupted by the clock, the iret instruction (back to task1) makes bochs crash with error:
Code: Select all
WARNING: Encountered an unknown instruction (signalling illegal instruction)
just before the clock interrupt switches from task2 to task1, i added
-one line of code that prints out the eip value stored in task1 tss
-another line of code that prints out the address of task1
because task1 is so small and executes in a loop, these two values should be very close to each other, but they are not!
it tells me that task1 starts at address 2088 and the eip values stored in the eip is 3229 (decimal values)!
how is that possible?
see below the clock handler:
Code: Select all
procedure clock_int; @nodisplay; @noalignstack; @noframe;
begin clock_int;
push(eax);
push(ebx);
pushfd();
streg(ax);
if (ax = IDX_KERNELTSS*@size(segdesc)) then
mov(IDX_TASK1TSS*@size(segdesc),kernelstate.backlink); //set the backlink
mov(GDT_BASE,eax); //set
add(IDX_TASK1TSS*@size(segdesc),eax); //busy
fseg: mov((type segdesc [eax]).props1,bl); //flag
or(%00000010,bl); //for incoming
fseg: mov(bl,(type segdesc [eax]).props1); //task
elseif (ax = IDX_TASK1TSS*@size(segdesc)) then
mov(IDX_TASK2TSS*@size(segdesc),task1state.backlink); //set the backlink
mov(GDT_BASE,eax); //set
add(IDX_TASK2TSS*@size(segdesc),eax); //busy
fseg: mov((type segdesc [eax]).props1,bl); //flag
or(%00000010,bl); //for incoming
fseg: mov(bl,(type segdesc [eax]).props1); //task
else
mov(IDX_TASK1TSS*@size(segdesc),task2state.backlink); //set the backlink
mov(GDT_BASE,eax); //set
add(IDX_TASK1TSS*@size(segdesc),eax); //busy
fseg: mov((type segdesc [eax]).props1,bl); //flag
or(%00000010,bl); //for incoming
fseg: mov(bl,(type segdesc [eax]).props1); //task
putunsint(&task1); //print address of task1
putchar(LF);
putunsint(task1state.eip_reg); //print backed-up eip
putchar(LF);
endif;
mov(PIC_EOI,al);
out(al,PIC1_COMMAND);
pop(eax); //popping the flags so I can set the NT bit
or($4000,eax);
push(eax);
popfd();
pop(ebx);
pop(eax);
iret();
end clock_int;
edit: i just found something else out: the address that gets stored in the esp field of the tss segment on a hardware task switch is the address just after the iret in the clock handler
this doesnt help of course
so this means i must not execute the iret in the clock handler, but rather in the code of the task itself...but this is useless, because how am i going to implement preemptive multitasking if i have to rely on each task to execute iret???