GPF When three or more threads running

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

GPF When three or more threads running

Post by Nessphoro »

Hey guys, perhaps anybody has experienced this problem before,
When I create three threads, the first one executed okay, so does the second one, but the third one causes GPF.

Threads are in Ring 0,
The opcodes at which it faults are 0xCD (int3) and 0xF|0xA9 which are not privileged instructions anyways.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: GPF When three or more threads running

Post by Combuster »

#GP instead of #DE on int3 means your IDT/GDT is messed up
#GP instead of #MF/#NM on what looks like an FPU opcode (please check!) means your IDT/GDT is messed up...

So probably your IDT/GDT got messed up :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: GPF When three or more threads running

Post by Nessphoro »

0xF|A9 Is "pop GS "
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: GPF When three or more threads running

Post by Nessphoro »

I traced to the point where the problem is, but I do not see why it causes a problem.

The behavior is very unusual, threads get switched in the right way, for some amount of time before it #GF on the task switch( Mostly)

EDIT: I found the reason, it happen because the stack has wrong values, but why? If it works lets say 10 seconds what corrupts the stack. Hmm...

EDIT 2:Quite the same problem as with the guy who posted "Strange stack clobber problem"
User avatar
mduft
Member
Member
Posts: 46
Joined: Thu Jun 05, 2008 9:23 am
Location: Austria

Re: GPF When three or more threads running

Post by mduft »

heh. yeah multi-threading and why things go wrong is pretty hard to grock :) can i help?

edit: what pit i fell into first was that i wasn't removing the error code from the stack, as the cpu never removes the error code. thus you have to add $0x4 (or $0x8, is it x86_64?) at the end of the interrupt handlers for it...
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: GPF When three or more threads running

Post by Nessphoro »

Yes, I have removed the error code. I have a unified stack regardless of error code being present or not, so I just ADD ESP,8 to clear it (Interrupt number is also passed there).

What happens is the ESP of the thread (where all the registers are stored), changes by a small amount, and the POP GS fails, because that Selector does not exist.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: GPF When three or more threads running

Post by gerryg400 »

Remember that when a stack switch occurs in long mode the new stack is forced to a 16 byte alignment by the processor. Is that the reason your stack 'changes by a small amount' ?

[edit] Ooops, sorry, thought you were in long mode.
Last edited by gerryg400 on Wed Aug 31, 2011 4:26 pm, edited 1 time in total.
If a trainstation is where trains stop, what is a workstation ?
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: GPF When three or more threads running

Post by Nessphoro »

No, I wouldn't say that, I'm not using long mode.
User avatar
mduft
Member
Member
Posts: 46
Joined: Thu Jun 05, 2008 9:23 am
Location: Austria

Re: GPF When three or more threads running

Post by mduft »

hm, not too many more ideas then. i've been using the IST from the very beginning of my kernel on, but AFAIK that is not available without long mode, right? do you actually switch stacks? or do you keep going with whatever comes along..?

are you willing to share some source that we can look at, or is it closed source? that would make analysis a little less guessing ;)
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: GPF When three or more threads running

Post by Nessphoro »

Certainly,

Switch tasks:

Code: Select all

           MOV ECX,0xDEADC0DE
	MOV EAX,[_SwitchRequested]
	CMP EAX,1
	JNE CleanUp ;Somewhere in the code there was a request to switch
	MOV BYTE [_SwitchRequested],0
	MOV ECX,0xDEAD7A6D
	CALL _GetNextThread
	MOV EAX,[_RunningThread] ;Get the Thread struct address
	MOV EBX,[EAX+12] ;PageDirectory
	MOV EBX,[EBX+0x2000] ;Physical
	MOV ECX,0xDEAD2E2
	MOV CR3,EBX

	;We're now in the next tasks VM
	MOV ECX,0xDEAD57AC
	MOV EAX,[EAX+4]
	MOV ESP,EAX
CleanUp:
    pop gs
    pop fs
    pop es
    pop ds
    popa
    add esp, 8
    iret
Next thread:

Code: Select all

extern "C" void GetNextThread()
{
    RunningThread->ESP0=(unsigned int)get_current_context();

    if(RunningThread->Parent->TaskID==1&&RunningThread->DontSave)
    {
        mem_copy(get_current_context(),RunningThread->Context,sizeof(context_86)); //This is to hack the kernel to run as a task
    }
    if(RunningThread->DontSave)
    {
        RunningThread->DontSave=false;
    }
    else
    {
        if(!RunningThread->VM)
            mem_copy(RunningThread->Context,get_current_context(),sizeof(context_86));
        else
            mem_copy(RunningThread->Context,get_current_context(),sizeof(context_86_vm));
        
    }
    while(RunningThread->Next->Exit)
    {   
        Thread* DeleteThread=RunningThread->Next;

        RunningThread->Next=RunningThread->Next->Next;

        EndThread(DeleteThread);
        //ParentTask->Threads->Delete(DeleteThread);
    }
    RunningThread=RunningThread->Next;
    while(RunningThread->Blocking)
    {
        while(RunningThread->Next->Exit)
        {
            Thread* DeleteThread=RunningThread->Next;

            RunningThread->Next=RunningThread->Next->Next;

            EndThread(DeleteThread);
            //ParentTask->Threads->Delete(DeleteThread);
        }
        RunningThread=RunningThread->Next;
    }

    if(!RunningThread->VM)
    set_kernel_stack(RunningThread->ESP0+sizeof(context_86));
    else
    set_kernel_stack(RunningThread->ESP0+sizeof(context_86_vm));
}
Post Reply