home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / os / linux / 8764 < prev    next >
Encoding:
Internet Message Format  |  1992-08-20  |  3.3 KB

  1. Path: sparky!uunet!mcsun!news.funet.fi!hydra!klaava!torvalds
  2. From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds)
  3. Newsgroups: comp.os.linux
  4. Subject: Re: A technical question on CONTEXT (TASK) SWITCHING by the Kernel
  5. Keywords: task switch, context switch, task state segment, kernel
  6. Message-ID: <1992Aug21.072548.10633@klaava.Helsinki.FI>
  7. Date: 21 Aug 92 07:25:48 GMT
  8. References: <1992Aug20.164928.24749@ramsey.cs.laurentian.ca>
  9. Organization: University of Helsinki
  10. Lines: 80
  11.  
  12. In article <1992Aug20.164928.24749@ramsey.cs.laurentian.ca> ron@ramsey.cs.laurentian.ca (Ron Prediger [Velociraptor]) writes:
  13. >Here is another technical question about the Linux kernel.  Context
  14. >switching in particular.
  15.  
  16. Ok, more answers...
  17.  
  18. >        #define switch_to(n) {\
  19. >        struct {long a,b;} __tmp;\
  20.  
  21. This just fools gcc to get 8 bytes of space on the stack, so that we
  22. don't have to get them anywhere else..
  23.  
  24. >        __asm__("cmpl %%ecx,_current\n\t"\
  25. >                "je 1f\n\t
  26.  
  27. %ecx is set up with the task we want to switch to when we enter the
  28. inline assembly statement, so this is obviosuly testing whether we are
  29. trying to switch to the current task, in which case nothing is done. 
  30. Besides being an obvious optimization, I don't think the 386 allows a
  31. tss-jump to the current task (but not having my books around me, I can't
  32. check). 
  33.  
  34. >                "movw %%dx, %1\n\t"\
  35.  
  36. This just moves %dx (which contains the tss-selector) into the word at
  37. __tmp+4. So ___tmp looks like this:
  38.  
  39. __tmp+0: undefined long
  40. __tmp+4: tss-selector word
  41. __tmp+6: undefined word
  42.  
  43. >                "xchgl %%ecx,_current\n\t"\
  44.  
  45. This exchanges %ecx and 'current' - %ecx will contain the task we are
  46. now executing in, and 'current' will contain the task we are just about
  47. to jump to.
  48.  
  49. >                "ljmp %0\n\t"\
  50.  
  51. This does the actual task switch: we do an indirect long-jump to __tmp.
  52. This is also the reason we updated just the word at __tmp+4: a long jump
  53. to a new tss-selector will ignore all other values. It will
  54. automatically jump to the place indicated by the tss segment.
  55.  
  56. >                "cmpl %%ecx,_last_task_used_math\n\t"\
  57.  
  58. Yes, this looks illogical: we just did an unconditional jump, and this
  59. should never be reached.  Right? Wrong.  The ljmp will return once some
  60. other task does it's own ljmp to this task.  Now %ecx contains the
  61. current task, so we check if this is the task that used the math
  62. coprocessor last... 
  63.  
  64. >                "jne 1f\n\t"\
  65. >                "clts\n"\
  66.  
  67. ...in which case we can clear the TS flag, giving better
  68. math-performance. Due to these three lines, linux never saves math state
  69. unnecessarily.
  70.  
  71. >                "1:"\
  72. >                "::"m" (*&__tmp.a),"m" (*&__tmp.b), \
  73.  
  74. This just sets up %0 - pointing to '__tmp', and %1, pointing to
  75. '__tmp+4'.
  76.  
  77. >                "d" (_TSS(n)), "c" ((long) task[n]) \
  78.  
  79. %dx contains the tss-descriptor for the task we want to switch to, and
  80. %ecx contains the task-pointer of the task we want to switch to.
  81.  
  82. >                :"cx");\
  83.  
  84. And this just tells gcc that %ecx is changed by the inline-asm.
  85.  
  86. That's it: 8 lines of assembly does the linux context switch with
  87. math-state optimizations.  Note that newer sources should have a cli-sti
  88. pair around the "xchg %%ecx,_current ; ljmp %0", so that 'current' is
  89. always up-to-date, even when running under interrupts.
  90.  
  91.         Linus
  92.