Page 1 of 1
context switching question (yet another)
Posted: Mon Aug 10, 2020 1:45 am
by ITchimp
I am still reading james molloy's context switch code, the code block that does the indirect jump, is wrapped around cli, and sti...
but was it necessary? cli and sti are already used in the glue code...
so does it make sense to actually enable interrupt?
this could actually introduce recursive interrupt, an interrupt that interrupt another ISR
Code: Select all
// Here we:
// * Stop interrupts so we don't get interrupted.
// * Temporarily put the new EIP location in ECX.
// * Load the stack and base pointers from the new task struct.
// * Change page directory to the physical address (physicalAddr) of the new directory.
// * Put a dummy value (0x12345) in EAX so that above we can recognise that we've just
// switched task.
// * Restart interrupts. The STI instruction has a delay - it doesn't take effect until after
// the next instruction.
// * Jump to the location in ECX (remember we put the new EIP in there).
asm volatile(" \
cli; \
mov %0, %%ecx; \
mov %1, %%esp; \
mov %2, %%ebp; \
mov %3, %%cr3; \
mov $0x12345, %%eax; \
sti; \
jmp *%%ecx "
: : "r"(eip), "r"(esp), "r"(ebp), "r"(current_directory->physicalAddr));
}
Re: context switching question (yet another)
Posted: Mon Aug 10, 2020 3:43 am
by iansjack
You've already asked this question and had it answered.
Re: context switching question (yet another)
Posted: Mon Aug 10, 2020 12:34 pm
by ITchimp
no, the pasted content is from jame molloy, I think he is wrong... you have said his code is insane!!!
Let me rephrase my question....
James molloy's context switching code includes cli and sti ..
but the assembly glue code that wraps around ISR already disabled then enabled interrupt...
then james molloy's code effectively start interrupt inside the glue code... which could lead to
interrupt inside interrupt...
any comment?
Re: context switching question (yet another)
Posted: Mon Aug 10, 2020 2:01 pm
by iansjack
Re: context switching question (yet another)
Posted: Mon Aug 10, 2020 3:40 pm
by Octocontrabass
ITchimp wrote:I am still reading james molloy's context switch code,
Why? Wouldn't it make more sense to read context switch code that isn't completely insane?
Re: context switching question (yet another)
Posted: Mon Aug 10, 2020 8:16 pm
by ITchimp
I am also reading linux and minix context switching code.. for big project like that stuff tend to get very hard to understand!!!
Re: context switching question (yet another)
Posted: Tue Aug 11, 2020 1:58 am
by iansjack
You might find this online course rather more useful than the tutorial you are currently following:
https://ocw.mit.edu/courses/electrical- ... /index.htm
It's not something that you can follow parrot fashion, but if you read all the lecture notes and complete all the labs you will end up with a decent understanding of the subject. It will require a lot of work on your part, but there's no royal road to OS development.
Re: context switching question (yet another)
Posted: Tue Aug 11, 2020 11:06 am
by thewrongchristian
ITchimp wrote:I am also reading linux and minix context switching code.. for big project like that stuff tend to get very hard to understand!!!
You might also want to look at GNU Pth, and its associated documentation and paper. The paper includes a description of how context switching is done in a portable manner (ie. no inline assembler.)
In short, switching contexts within the kernel itself is simply a stack change, and can be as simple as using setjmp/longjmp. Once your thread is bootstrapped (got a stack and is executing somewhere), calling setjmp can be used to save its context, then you longjmp to the context you want to switch to. setjmp will handle the saving of the ABI callee saved registers (including stack pointer), and longjmp will restore those registers that the ABI requires to be preserved.
So a context switch becomes something like:
Code: Select all
void switchcontext(context * current, context * next)
{
if (0==setjmp(current->jmpbuf)) {
/* Context saved, switch to next */
longjmp(next->jmpbuf, 1);
}
}
Now, setjmp/longjmp will be architecture dependent, but that can be provided by the compiler which knows the ABI, so you may not even have to write those (I do my own version, but I may investigate using the compiler intrinsic versions.) Note, you don't need to save all the registers. You only have to save the registers required by the ABI.
All you'll need then is a way to craft a new context. That would require a new stack (and hence, writing a new SP) and calling into a function, but that's quite easy to do in assembler. I'll leave that as an exercise for you.
User registers should be saved/restored to/from the trapframe used when moving from user->kernel space, but that's a separate problem you won't have until you have user space processes.
https://www.gnu.org/software/pth/
Re: context switching question (yet another)
Posted: Tue Aug 11, 2020 12:04 pm
by iansjack
Aren't setjmp/longjmp part of the C standard library? So surely you have to write your own versions - which is where we came in.
Re: context switching question (yet another)
Posted: Tue Aug 11, 2020 12:38 pm
by thewrongchristian
iansjack wrote:Aren't setjmp/longjmp part of the C standard library? So surely you have to write your own versions - which is where we came in.
True, which is why I did write my own, but libgcc provides built in versions I understand.
But in terms of getting your head round the mechanics of context switching, this can be done entirely in userspace using already provided setjmp/longjmp. I found the pth paper very useful, for example. Certainly more useful than dubious inline assembly to achieve essentially the same job.
Re: context switching question (yet another)
Posted: Tue Aug 11, 2020 12:53 pm
by nullplan
iansjack wrote:Aren't setjmp/longjmp part of the C standard library? So surely you have to write your own versions - which is where we came in.
They are, but maybe the snippet might make it clear to the OP. setjmp and longjmp are actually pretty easy to write once you know what you are doing. You only have to save all non-volatile (callee-saved) registers, as well as the return address. Then, in longjmp(), you just restore those. To give an example (that won't help the OP directly, but this is by design): On PowerPC, a function has to preserve R1 (stack pointer), R2 (small data area pointer), R13-R31, and certain sections of the condition register. Also of course floating-point stuff, but that does not matter to a kernel. So, that is 22 registers and the return address. So:
Code: Select all
typedef unsigned long jmp_buf[23];
int setjmp(jmp_buf*);
int longjmp(jmp_buf*, int);
Code: Select all
setjmp:
mflr r0 #load link register into r0
mfcr r4 #load condition register into r4
stw r1,0(r3) #save r1
stw r2,4(r3) #save r2
stmw r13,8(r3) #save r13-r31
stw r0, 21*4(r3) #save link register
stw r4, 22*4(r3) #save condition register
li r3,0 #set return value to 0
blr #return
longjmp:
lwz r1,0(r3) #load r1 back
lwz r2,4(r3) #load r2 back
lmw r13,8(r3) #load r13-r31 back
lwz r0, 21*4(r3) #load old LR into r0
lwz r5, 22*4(r3) #load old CR into r5
mtlr r0 #restore LR
mtcr r5 #restore CR
mr. r3,r4 #move return value over to R3, testing for equality with 0
bne 1f #if it is:
li r3,1 #set return value to 1
1:
blr #return
There you go. Now you might only need to add an enum so that you can know in C code where to put what in a new jmp_buf if you construct one from scratch. That way you can create a new jmp_buf that was never saved with setjmp() for a new task.
Now it's your turn for your architecture.
Re: context switching question (yet another)
Posted: Tue Aug 11, 2020 1:01 pm
by nexos
My context swapping code has the ISR handler push the register state on the stack, and then save and loading the state involves reading or changing the values on the stack. When all is said and done, the ISR handler pop everything off the stack and hence loads the new state. Hence, it makes context swaps easy. Blocking a process now involves manually reading the registers, which makes things more difficult, but not to difficult. Hopefully that makes sense