context switching question (yet another)

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
ITchimp
Member
Member
Posts: 134
Joined: Sat Aug 18, 2018 8:44 pm

context switching question (yet another)

Post 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));
}
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: context switching question (yet another)

Post by iansjack »

You've already asked this question and had it answered.
ITchimp
Member
Member
Posts: 134
Joined: Sat Aug 18, 2018 8:44 pm

Re: context switching question (yet another)

Post 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?
Last edited by ITchimp on Mon Aug 10, 2020 3:29 pm, edited 1 time in total.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: context switching question (yet another)

Post by iansjack »

Octocontrabass
Member
Member
Posts: 5572
Joined: Mon Mar 25, 2013 7:01 pm

Re: context switching question (yet another)

Post 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?
ITchimp
Member
Member
Posts: 134
Joined: Sat Aug 18, 2018 8:44 pm

Re: context switching question (yet another)

Post 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!!!
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: context switching question (yet another)

Post 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.
thewrongchristian
Member
Member
Posts: 426
Joined: Tue Apr 03, 2018 2:44 am

Re: context switching question (yet another)

Post 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/
Last edited by thewrongchristian on Tue Aug 11, 2020 5:12 pm, edited 1 time in total.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: context switching question (yet another)

Post 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.
thewrongchristian
Member
Member
Posts: 426
Joined: Tue Apr 03, 2018 2:44 am

Re: context switching question (yet another)

Post 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.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: context switching question (yet another)

Post 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.
Carpe diem!
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: context switching question (yet another)

Post 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 :)
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Post Reply