ࡱ;   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry  !"#$%&'()+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm ®`VTextStarWriter 5.0@@{:` SfxDocumentInfo Mike |1#Mike P|1$}Mike |1,C Info 0 Info 1 Info 2 Info 3 |1"T<44Standard LIBIMBEDDED LIBIMBEDDED TASK,0,1,H32,0,100,1,2368;218634;110;0;213056;14971;221360;0;0SW5HDR.0P|1$}!8Footnote Symbol Footnote anchorOutline0 #ZSBX sb Z Standard StarBASICSBX ARSBX AR SBX AR2c%bqqSWG, A<  #$%&'()*./0123456789:;<=>?@ABCDGHK  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFQRSTU0%'@t:eX'@d X'(!@. '. X@'1!@dddXJJ@X/SP$' '(. . p. @ . . . . . P. . . !. $. `'. 0*. -. /. 2. p5. @8. ;. =. @. 6')^2P PFootnote SymbolFootnote SymbolFootnote anchorFootnote anchor%' StandardStandard@FootnoteStandardFootnote@'1@'JJ FooterStandardFooter@('JJJOh+'0 h t 27@@L@;@jě@0iNMike Mike SW5HDR.0P|1$}! Frameformat ZeichenformatTextformatvorlageStandard FootnoteFooterFootnote Symbol Footnote anchorRoot 9Standard  Illustration Table TextDrawingY  .Y  .Y  .Y  .q= GeneralGeneraldNC#,###.00#,###.00SystemNC #,##0.00 CCC#,##0.00 CCCNC$#,##0.--;[RED]-$#,##0.-- $#,##0.---$#,##0.--REDNC$ MM/DD/YYYYMM/DD/YYYY def/SystemNC%MM/DD/YYMM/DD/YY def/SystemNC&NNNNMMMM DD, YYYYNNNNMMMM  DD, YYYYSystemNC' MMM D, YYMMM D, YY def/SystemNC. [HH]:MM:SS.00 [HH ]:MM:SS .00NC3MM/DD/YYYY HH:MM:SS MM/DD/YYYY HH :MM:SS  NCK MMM D, YYYYMMM D, YYYY def/SystemNCL MMMM D, YYYYMMMM  D, YYYY def/SystemNCM NN, MMM D, YYNN, MMM D, YY def/SystemNCNNN, MMMM D, YYYYNN, MMMM  D, YYYY def/SystemNCONNNNMMMM D, YYYYNNNNMMMM  D, YYYY def/SystemNCP D. MMM. YYYYD. MMM. YYYYDIN 5008 (EN 28601)NCQ D. MMMM YYYYD. MMMM  YYYYDIN 5008 (EN 28601)NCRMM-DDMM-DDDIN 5008 (EN 28601)NCSYY-MM-DDYY-MM-DDDIN 5008 (EN 28601)NCT YYYY-MM-DDYYYY-MM-DDDIN 5008 (EN 28601)NCUWWWWNCBXoeP<p5 2$99 SAP/=APdddAPddA PAu Prk FooterSYAPddADPN;T2SA @A0SAAP/=APdddAPddZSW5HDR.0P|1$}C(569a(Build:5169)(SV569)]D!Address Book Fileaddress! Frameformat ZeichenformatTextformatvorlageStandard FootnoteFooterFootnote Symbol Footnote anchorRoot 9Standard  Illustration Table TextDrawingd y E14 5*jK standard.dic soffice.dicZsun.dic@ IgnoreAllListY  .Y  .Y  .Y  .6NKTMScheduleSA A @A!8 TimesNewRomanTAS6A TimesNewRomanA A @TW!The schedule function implements S+A TimesNewRomanA TDS9APdddA TimesNewRomanTy5the scheduling policy (deciding which process to run)S9APdddA TimesNewRomanT~6the scheduling mechanism (performing context switches)SAPdddA!86 TimesNewRomanTDS9APdddA TimesNewRomanTHschedule() is invoked directly or indirectly by several kernel routines S9APdddA TimesNewRomanTDS9APdddA TimesNewRomanTz6Direct invocation was seen in interruptible_sleep_on()S9APdddA TimesNewRomanTDS9APdddA TimesNewRomanT<Indirect invocation is by setting current->need_resched = 1;S9APdddA TimesNewRomanT;This value is always checked before returning to user mode.S9APdddA TimesNewRomanA8 A8 ;TNSCAPdddA TimesNewRomanA  TfLazy invocation examplesSCAPdddA TimesNewRomanA  TNSCAPdddA TimesNewRomanA  Tz,time quantum expired in update_process_timesSCAPpdddpA TimesNewRomanA  T2process with higher priority than current wakes upSCAPpdddpA TimesNewRomanA  T~0(via reschedule_idle() called by try_to_wakeup()SCAP@ ddd@ A TimesNewRomanA  TDS9APdddA TimesNewRomanTcThe entry to scheduleSCAPdddA TimesNewRomanA TDS9APdddA TimesNewRomanTH"534 asmlinkage void schedule(void)SACourierT+535 {SACourierTT.536 struct schedule_data * sched_data;SACourierTV0537 struct task_struct *prev, *next, *p;SACourierTH"538 struct list_head *tmp;SACourierTB539 int this_cpu, c;SACourierT*540 SACourierT,S!A TimesNewRomanT,S!A TimesNewRomanTWThis simply reads the value of the runqueue_lock.. presumably for cache related reasonsS!A TimesNewRomanT,S!A TimesNewRomanT*541 SACourierTU/542 spin_lock_prefetch(&runqueue_lock);SACourierT*543 SACourierT TSA PTxLEvery process has two mm (memory mgmt) structure pointers in the task_structS!A TimesNewRomanTFmmS9APdddA TimesNewRomanTM active_mmS9APdddA TimesNewRomanTDS9APdddA TimesNewRomanTw3For "regular" processes they have the same value. S9APdddA TimesNewRomanT|P For kernel threads mm = 0 and active_mm is the mm of the last "regular" processS!A TimesNewRomanT}9Since kernel threads don't touch user memory, this is OK.S9APdddA TimesNewRomanT,S!A TimesNewRomanTQ+544 if (!current->active_mm) BUG();SACourierT<545 need_resched_back:SACourierT&SACourierT{OFor the rest of the way prev points to the task_struct about to be unscheduled.S!A TimesNewRomanTa5Remember CPU id to access kernel lock and sched data.S!A TimesNewRomanT&SACourierTA546 prev = current;SACourierTM'547 this_cpu = prev->processor;SACourierT*548 SACourierT,S!A TimesNewRomanTTScheduling within an interrupt handler is strictly verboten and causes system crash!S!A TimesNewRomanTmAThus, as a consequence, so does sleeping in an interrupt handler.S!A TimesNewRomanT,S!A TimesNewRomanTQ+549 if (unlikely(in_interrupt())) {SACourierT^8550 printk("Scheduling in interrupt\n");SACourierT@551 BUG();SACourierT3 552 }SACourierT6S+A TimesNewRomanA  TnUnlikely is a macro designed to help the compiler avoid pipeline stalls caused by incorrect branch prediction.S!A TimesNewRomanA8 T,S!A TimesNewRomanTN4 /* Somewhere in the middle of the GCC 2.96 development cycle, we implementedSBAPdddACourierAd TL5 a mechanism by which the user can annotate likely branch directions andSBAPdddACourierAd TN6 expect the blocks to be reordered appropriately. Define __builtin_expectSBAPdddACourierAd Tw*7 to nothing for earlier compilers. */SBAPdddACourierAd TO8 SBAPdddACourierAd Tw*9 #if __GNUC__ == 2 && __GNUC_MINOR__ < 96SBAPdddACourierAd T210 #define __builtin_expect(x, expected_value) (x)SBAPdddACourierAd TV 11 #endifSBAPdddACourierAd TP12 SBAPdddACourierAd T213 #define likely(x) __builtin_expect((x),1)SBAPdddACourierAd T214 #define unlikely(x) __builtin_expect((x),0)SBAPdddACourierAd TP15 SBAPdddACourierAd To"16 #endif /* __LINUX_COMPILER_H */SBAPdddACourierAd TP17 SBAPdddACourierAd T;S0A TimesNewRomanAd TES:A PA TimesNewRomanAd Tc7Don't want to hold kernel lock while no longer running!S!A TimesNewRomanT,S!A TimesNewRomanTV0554 release_kernel_lock(prev, this_cpu);SACourierT*555 SACourierT,S!A TimesNewRomanTuISetup local pointer to schedule_data and grab runqueue lock (read above).S!A TimesNewRomanT,S!A TimesNewRomanT*555 SACourierT/ 556 /*SACourierTe?557 * 'sched_data' is protected by the fact that we can runSACourierTI#558 * only one process per CPU.SACourierT0 559 */SACourierTa;560 sched_data = & aligned_data[this_cpu].schedule_data;SACourierT*561 SACourierTK%562 spin_lock_irq(&runqueue_lock);SACourierT)563SACourierT,S!A TimesNewRomanTl@RR (round robin) processes are by definition real time processesS!A TimesNewRomanTnBWhen the exhaust their quanta they move to the end of the runqueueS!A TimesNewRomanT,S!A TimesNewRomanT[5564 /* move an exhausted RR process to be last.. */SACourierTS-565 if (unlikely(prev->policy == SCHED_RR))SACourierTI#566 if (!prev->counter) {SACourierTc=567 prev->counter = NICE_TO_TICKS(prev->nice);SACourierTU/568 move_last_runqueue(prev);SACourierT5569 }SACourierT*570 SACourierT,S!A TimesNewRomanTeIf the task is neither running nor interruptible with a signal pending remove it from the run queue. S!A TimesNewRomanA8 15A8 5eT\Here a process which calls schedule in the middle of sleep_on() is removed from the runqueueS!A TimesNewRomanT,S!A TimesNewRomanTH"571 switch (prev->state) {SACourierTR,572 case TASK_INTERRUPTIBLE:SACourierT]7573 if (signal_pending(prev)) {SACourierTe?574 prev->state = TASK_RUNNING;SACourierTP*575 break;SACourierTC576 }SACourierTB577 default:SACourierTZ4578 del_from_runqueue(prev);SACourierTM'579 case TASK_RUNNING:;SACourierT3 580 }SACourierT,S!A TimesNewRomanTPSince we are now doing the resched, clear the flag indicating that it is needed.S!A TimesNewRomanA8 A8 PT,S!A TimesNewRomanTI#581 prev->need_resched = 0;SACourierT*582 SACourierT,S!A TimesNewRomanT,S!A TimesNewRomanTY The task selection logicS5A PA TimesNewRomanA T,S!A TimesNewRomanT=Linux provides a preemptive, priority based scheduling systemS9APdddA TimesNewRomanT~:The standard time quantum is 20 jiffies (ticks) or 200 ms.S9APdddA TimesNewRomanTDS9APdddA TimesNewRomanT{7Linux supports three priority based scheduling policiesS9APdddA TimesNewRomanTDS9APdddA TimesNewRomanTSCHED_FIFO - Real-time process that runs until completion unless a higher priority process becomes ready. Scheduling order is based on p->rt_prioritySJAPdddoA TimesNewRomanA@. TV SJAPdddoA TimesNewRomanA@. TSCHED_RR - Real-time processes that are RR unscheduled on using up their quantum (but still run ahead of conventional processes)SJAPdddoA TimesNewRomanA@. TUSJAPdddoA TimesNewRomanA@. TQSCHED_OTHER - Regular processes that are scheduled using the value of p->counter SJAPdddoA TimesNewRomanA@. T'SAPdddTj&Here is the basic task selection loop.S9APdddA TimesNewRomanTDS9APdddA TimesNewRomanT:587 repeat_schedule:SACourierT4588 /*SACourierTP*589 * Default process to select..SACourierT5590 */SACourierTM'591 next = idle_task(this_cpu);SACourierT<592 c = -1000;SACourierTV0593 list_for_each(tmp, &runqueue_head) {SACourierTsM594 p = list_entry(tmp, struct task_struct, run_list);SACourierTZ4595 if (can_schedule(p, this_cpu)) {SACourierTZ596 int weight = goodness(p, this_cpu, prev->active_mm);SACourierTQ+597 if (weight > c)SACourierT_9598 c = weight, next = p;SACourierT;599 }SACourierT3 600 }SACourierT&SACourierT&SACourierT0S%A PACourierT]1The determination of goodness is made as follows:S!A TimesNewRomanT,S!A TimesNewRomanT_144 static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm)SACourierT+145 {SACourierT6146 int weight;SACourierT*147 SACourierT,148 /*SACourierTY3149 * select the current process after every otherSACourierTZ4150 * runnable process, but before the idle thread.SACourierTX2151 * Also, dont trigger a counter recalculation.SACourierT-152 */SACourierT7153 weight = -1;SACourierTG!154 if (p->policy & SCHED_YIELD)SACourierT4155 goto out;SACourierT*156 SACourierT-157 /*SACourierTR,158 * Non-RT process - normal case first.SACourierT-159 */SACourierTJ$160 if (p->policy == SCHED_OTHER) {SACourierT-161 /*SACourierTb<162 * Give the process a first-approximation goodness valueSACourierT`:163 * according to the number of clock-ticks it has left.SACourierT+164 *SACourierTa;165 * Don't do any other calculations if the time slice isSACourierT3 166 * over..SACourierT-167 */SACourierT?168 weight = p->counter;SACourierT7169 if (!weight)SACourierT5170 goto out;SACourierT*171 SACourierT<172 #ifdef CONFIG_SMPSACourierTd>173 /* Give a largish advantage to the same processor... */SACourierTd>174 /* (this is equivalent to penalizing other processors) */SACourierTH"175 if (p->processor == this_cpu)SACourierTJ$176 weight += PROC_CHANGE_PENALTY;SACourierT1 177 #endifSACourierT*178 SACourierT\6179 /* .. and a slight advantage to the current MM */SACourierTJ$180 if (p->mm == this_mm || !p->mm)SACourierT8181 weight += 1;SACourierTB182 weight += 20 - p->nice;SACourierT4183 goto out;SACourierT+184 }SACourierT*185 SACourierT&SACourierT7186 /*S%A PACourierTZ4187 * Realtime process, select the first one on theSACourierTY3188 * runqueue (taking priorities within processesSACourierT;189 * into account).SACourierT-190 */SACourierTJ$191 weight = 1000 + p->rt_priority;SACourierT/ 192 out:SACourierT9193 return weight;SACourierT+194 }SACourierT,S!A TimesNewRomanTGScheduling epochsS+A TimesNewRomanA T6S+A TimesNewRomanA TCAn epoch ends when the max goodness of all runnable processes is 0.SJAPdd,dA TimesNewRomanA@. T6At this point it is necessary to reset all p->countersSJAPdd,dA TimesNewRomanA@. TMThis recomputation is done for all processes not just those that are runnableSJAPdd,dA TimesNewRomanA@. A8 "A8 "MT_Note that the amount remaining in the quantum is divided by 2 and then a fixed amount is added.STAPdd,dA TimesNewRomanA  A@. T0How does this affect a process in a long sleep??SCAPdddA TimesNewRomanA  A8 $(T- S!A TimesNewRomanT*601 SACourierT\6602 /* Do we need to re-calculate counters? */SACourierTE603 if (unlikely(!c)) {SACourierTP*604 struct task_struct *p;SACourierT*605 SACourierTZ4606 spin_unlock_irq(&runqueue_lock);SACourierTT.607 read_lock(&tasklist_lock);SACourierTJ$608 for_each_task(p)SACourierT\609 p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);SACourierTV0610 read_unlock(&tasklist_lock);SACourierTX2611 spin_lock_irq(&runqueue_lock);SACourierTO)612 goto repeat_schedule;SACourierT3 613 }SACourierT*614 SACourierTDS9APdddA TimesNewRomanTOThe NICE_TO_TICKS increment depends on the basic tick rate HZ (normally 100 hz)SCAPdddA PA TimesNewRomanTDS9APdddA TimesNewRomanTG 44 /*S3APdddACourierTZ 45 * Scheduling quanta.S3APdddACourierTG 46 *S3APdddACourierTC 47 * NOTE! The unix "nice" value influences how long a processS3APdddACourierTB 48 * gets. The nice value ranges from -20 to +19, where a -20S3APdddACourierTB 49 * is a "high-priority" task, and a "+10" is a low-priorityS3APdddACourierTM 50 * task.S3APdddACourierTG 51 *S3APdddACourierTA 52 * We want the time-slice to be around 50ms or so, so thisS3APdddACourierTo1 53 * calculation depends on the value of HZ.S3APdddACourierTH 54 */S3APdddACourierTQ 55 #if HZ < 200S3APdddACourierTg) 56 #define TICK_SCALE(x) ((x) >> 2)S3APdddACourierTS 57 #elif HZ < 400S3APdddACourierTg) 58 #define TICK_SCALE(x) ((x) >> 1)S3APdddACourierTS 59 #elif HZ < 800S3APdddACourierT`" 60 #define TICK_SCALE(x) (x)S3APdddACourierTT 61 #elif HZ < 1600S3APdddACourierTg) 62 #define TICK_SCALE(x) ((x) << 1)S3APdddACourierTJ 63 #elseS3APdddACourierTg) 64 #define TICK_SCALE(x) ((x) << 2)S3APdddACourierTK 65 #endifS3APdddACourierTD 66S3APdddACourierT|> 67 #define NICE_TO_TICKS(nice) (TICK_SCALE(20-(nice))+1)S3APdddACourierTD 68S3APdddACourierTDS9APdddA TimesNewRomanTvMechanics of making the switchSMAPdddA PA TimesNewRomanA T,S!A TimesNewRomanTSSave state infoS9APdddA TimesNewRomanT]Release runqueue lockSAPdddA!8 TimesNewRomanTf"And check for resched same processS9APdddA TimesNewRomanTDS9APdddA TimesNewRomanT4615 /*SACourierTc=616 * from this point on nothing can prevent us fromSACourierTb<617 * switching to the next task, save this fact inSACourierT@618 * sched_data.SACourierT5619 */SACourierTJ$620 sched_data->curr = next;SACourierTO)621 task_set_cpu(next, this_cpu);SACourierTR,622 spin_unlock_irq(&runqueue_lock);SACourierT*623 SACourierTO)624 if (unlikely(prev == next)) {SACourierT|V625 /* We won't go through the normal tail, so do this by hand */SACourierTW1626 prev->policy &= ~SCHED_YIELD;SACourierTL&627 goto same_process;SACourierT3 628 }SACourierT*629 SACourierT,S!A TimesNewRomanTThe second block comment appears to be saying that we don't want to allow "prev" to be dispatched on another CPU before we finish saving its context on this one..S!A TimesNewRomanT,S!A TimesNewRomanTP$So why is there no code to do that??S!A TimesNewRomanT,S!A TimesNewRomanT;630 #ifdef CONFIG_SMPSACourierT.631 /*SACourierT^8632 * maintain the per-process 'last schedule' value.SACourierTd>633 * (this has to be recalculated even if we reschedule toSACourierTd>634 * the same process) Currently this is only used on SMP,SACourierTb<635 * and it's approximate, so we do not have to maintainSACourierTV0636 * it while holding the runqueue spinlock.SACourierT/ 637 */SACourierTU/638 sched_data->last_schedule = get_cycles();SACourierT*639 SACourierT.640 /*SACourierTiC641 * We drop the scheduler lock early (it's a global spinlock),SACourierTe?642 * thus we have to lock the previous process from gettingSACourierTN(643 * rescheduled during switch_to().SACourierT.644 */SACourierT*645 SACourierTA646 #endif /* CONFIG_SMP */SACourierT*647 SACourierTH"648 kstat.context_swtch++;SACourierT&SACourierT,S!A TimesNewRomanTXMemory context switchingS5A PA TimesNewRomanA T,S!A TimesNewRomanTl@Ifthe next process to run is a kernel thread next->mm will be 0.S!A TimesNewRomanTl@In that case next->active_mm is set to the previously active_mm.S!A TimesNewRomanTxLIn these cases a process switch does not requrire an mm (page-table) switch.S!A TimesNewRomanT,S!A TimesNewRomanTUIf the new process does have its own mm. Then it is necessary to switch page tables.S!A TimesNewRomanTX,Both prepare_to_switch() is a no-op on a UP.S!A TimesNewRomanT,S!A TimesNewRomanTF 658 prepare_to_switch(); SACourierT0 659 {SACourierTW1660 struct mm_struct *mm = next->mm;SACourierTa;661 struct mm_struct *oldmm = prev->active_mm;SACourierTA662 if (!mm) {SACourierTZ4663 if (next->active_mm) BUG();SACourierTW1664 next->active_mm = oldmm;SACourierT\6665 atomic_inc(&oldmm->mm_count);SACourierTe?666 enter_lazy_tlb(oldmm, next, this_cpu);SACourierT?667 } else {SACourierT`:668 if (next->active_mm != mm) BUG();SACourierTd>669 switch_mm(oldmm, mm, next, this_cpu);SACourierT8670 }SACourierT*671 SACourierT TdDecrement the use count associated with this memory context and if it reaches 0, delete the context.S!A TimesNewRomanT- S!A TimesNewRomanTJ$672 if (!prev->mm) {SACourierTY3673 prev->active_mm = NULL;SACourierTP*674 mmdrop(oldmm);SACourierT;675 }SACourierT3 676 }SACourierT*677 SACourierT,S!A TimesNewRomanT6S+A PA TimesNewRomanTyMThe actual context switch is hardware dependent and done in assembly languageS!A TimesNewRomanTg;__schedule_tail simply unsets the SCHED_YIELD flag on a UP.S!A TimesNewRomanT,S!A TimesNewRomanT4678 /*SACourierTb<679 * This just switches the register state and theSACourierT;680 * stack.SACourierT5681 */SACourierTN(682 switch_to(prev, next, prev);SACourierTH"683 __schedule_tail(prev);SACourierT*684 SACourierT,S!A TimesNewRomanT]Here is where we end up if the previously running process is selected to be the next process.S!A TimesNewRomanT,S!A TimesNewRomanT7685 same_process:SACourierTQ+686 reacquire_kernel_lock(current);SACourierTL&687 if (current->need_resched)SACourierTQ+688 goto need_resched_back;SACourierT9689 return;SACourierT+690 }SACourierT\Low level context switching S5A PA TimesNewRomanA T TzNThis comment seems to have been trying to describe the operation of switch_to.S!A TimesNewRomanTVNote that the assembly language interface renders the parameters reference parameters S!A TimesNewRomanTC switch_to(prev, next, prev);A8CourierT-649 /*A8CourierTkE650 * there are 3 processes which are affected by a context switch:SACourierT-651 *SACourierTM'652 * prev == .... ==> (last => next)SACourierT+653 SACourierTkE654 * It's the 'much more previous' 'prev' that is on next's stack,SACourierTqK655 * but prev is set to (the just run) 'last' process by switch_to().SACourierTjD656 * This might sound slightly confusing but makes tons of sense.SACourierT.657 */SACourierT,S!A TimesNewRomanTh<The switch_to macro is written in embedded assembly languageS!A TimesNewRomanTUEmbedded assembly language is more difficult to grok than regular assembly language!S9APdddA TimesNewRomanA8 "A8 "UA004NT T(grok /grok/, var. /grok/ vt. T[common; from the novel "Stranger in a Strange Land", by Robert A. Heinlein, where it is a Martian word meaning literally `to drink' and metaphorically `to be one with'] The emphatic form is `grok in fullness'. 1. To understand. Connotes intimate and exhaustive knowledge. When you claim to `grok' some knowledge or technique, you are asserting that you have not merely learned it in a detached instrumental way but that it has become part of you, part of your identity. For example, to say that you "know" LISP is simply to assert that you can code in it if necessary - but to say you "grok" LISP is to claim that you have deeply entered the world-view and spirit of the language, with the implication that it has transformed your view of programming. Contrast zen, which is similar supernal understanding experienced as a single brief flash. See also glark. 2. Used of programs, may connote merely sufficient understanding. "Almost all C compilers grok the void type these days." TNSCAPdddA TimesNewRomanA  TjD16 #define switch_to(prev,next,last) do { \SACourierTjD17 asm volatile("pushl %%esi\n\t" \SACourierTjD18 "pushl %%edi\n\t" \SACourierTjD19 "pushl %%ebp\n\t" \SACourierTjD20 "movl %%esp,%0\n\t" /* save ESP */ \SACourierTjD21 "movl %3,%%esp\n\t" /* restore ESP */ \SACourierTjD22 "movl $1f,%1\n\t" /* save EIP */ \SACourierTjD23 "pushl %4\n\t" /* restore EIP */ \SACourierTjD24 "jmp __switch_to\n" \SACourierTjD25 "1:\t" \SACourierTjD26 "popl %%ebp\n\t" \SACourierTjD27 "popl %%edi\n\t" \SACourierTjD28 "popl %%esi\n\t" \SACourierTjD29 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \SACourierTjD30 "=b" (last) \SACourierTjD31 :"m" (next->thread.esp),"m" (next->thread.eip), \SACourierTjD32 "a" (prev), "d" (next), \SACourierTjD33 "b" (prev)); \SACourierT434 } while (0)SACourierT(35SACourierT' SACourierT&SACourierTTo see whats really upSxAPdddA TimesNewRomanAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. T&Add a switch_to your ATM device driverSxAPdddA TimesNewRomanAd A  A A @A@. TThen add an -S to the CFLAGSSxAPdddA TimesNewRomanAd A  A A @A@. TThen make yielding .s filesSxAPdddA TimesNewRomanAd A  A A @A@. TEThen as -a atmbase.s > atmbase.lst to obtain a listing such as shown.SxAPdddA TimesNewRomanAd A  A A @A@. TZThis technique is also useful when debugging drivers from screen dumps after kernel faultsSxAPdddA TimesNewRomanAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. T;This first part is automatically inserted by the compiler..SxAPdddA TimesNewRomanAd A  A A @A@. THHere you see parameters 1 and 2 (prev and next) -> registers ecx and edxSxAPdddA TimesNewRomanAd A  A A @A@. T SxAPdddA TimesNewRomanAd A  A A @A@. T" 2433 .globl dummy1SrAPdddACourierAd A  A A @A@. T/ 2434 .type dummy1,@functionSrAPdddACourierAd A  A A @A@. T 2435 dummy1:SrAPdddACourierAd A  A A @A@. T& 2436 0000 8B0D0000 movl p1, %ecxSrAPdddACourierAd A  A A @A@. T 2436 0000SrAPdddACourierAd A  A A @A@. T" 2437 0006 53 pushl %ebxSrAPdddACourierAd A  A A @A@. T& 2438 0007 8B150000 movl p2, %edxSrAPdddACourierAd A  A A @A@. T 2438 0000SrAPdddACourierAd A  A A @A@. T( 2439 000d 89CB movl %ecx, %ebxSrAPdddACourierAd A  A A @A@. T( 2440 000f 89C8 movl %ecx, %eaxS8APdddA @A@. A8(A8 (A8(d A8(CourierTCS8APdddA @A@. T{8 These are the pushes that appear in the pseudo asm langS8APdddA @A@. TCS8APdddA @A@. T 2441 #APPSrAPdddACourierAd A  A A @A@. T" 2442 0011 56 pushl %esiSrAPdddACourierAd A  A A @A@. T" 2443 0012 57 pushl %ediSrAPdddACourierAd A  A A @A@. T" 2444 0013 55 pushl %ebpSrAPdddACourierAd A  A A @A@. T~ SrAPdddACourierAd A  A A @A@. T0Recall that register ecx -> prev and edx -> nextSxAPdddA TimesNewRomanAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. T 7616(%ecx)corresponds to %0 or :"=m" (prev->thread.esp) SxAPdddA TimesNewRomanAd A  A A @A@. A8 CourierA8CourierA86CourierT5616(%edx)corresponds to %3 or :"m" (next->thread.esp)S8APdddA @A@. A85CourierA8A8 A8d A!8  TimesNewRomanA8CourierT)5612(%ecx)corresponds to %1 or :"m" (prev->thread.eip)SOAPdddACourierA @A@. A8A8 A8d A8 A8  A8 d A!8  TimesNewRomanA8CourierTCS8APdddA @A@. TdSYAPdddA PACourierA @A@. TZSOAPdddACourierA @A@. TZSOAPdddACourierA @A@. T/The mechanics of the process switch occur here:SxAPdddA TimesNewRomanAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. TU The value $1f represents a relative offset that is converted to actual location 0x35SxAPdddA TimesNewRomanAd A  A A @A@. A8 CourierTU which is at the label 1: and is where the process will magically resume execution. SxAPdddA TimesNewRomanAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. T? 2445 0014 89A16802 movl %esp,616(%ecx) /* save ESP */ SrAPdddACourierAd A  A A @A@. T 2445 0000SrAPdddACourierAd A  A A @A@. T> 2446 001a 8BA26802 movl 616(%edx),%esp /* restore ESP */SrAPdddACourierAd A  A A @A@. T 2446 0000SrAPdddACourierAd A  A A @A@. T> 2447 0020 C7816402 movl $1f,612(%ecx) /* save EIP */SrAPdddACourierAd A  A A @A@. T 2447 00003500SrAPdddACourierAd A  A A @A@. T 2447 0000S8APdddA @A@. A8A8 A8d A8CourierT S8APdddA @A@. A8A8 A8d A8CourierTThis a pseudo CALL sequence. SxAPdddA TimesNewRomanAd A  A A @A@. T We push a desired return addressSxAPdddA TimesNewRomanAd A  A A @A@. T1jmp into the procedure instead of calling it and SxAPdddA TimesNewRomanAd A  A A @A@. T2return will be to the location pushed on the stackSxAPdddA TimesNewRomanAd A  A A @A@. TSwhich, in this case, appears to be generally the same result as calling (line 2447)SxAPdddA TimesNewRomanAd A  A A @A@. T SxAPdddA TimesNewRomanAd A  A A @A@. T> 2448 002a FFB26402 pushl 612(%edx) /* restore EIP */SrAPdddACourierAd A  A A @A@. T 2448 0000SrAPdddACourierAd A  A A @A@. T' 2449 0030 E9FCFFFF jmp __switch_toSrAPdddACourierAd A  A A @A@. T 2449 FFSrAPdddACourierAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. TYHere is where each process resumes execution after being preempted or volutarily sleepingSxAPdddA TimesNewRomanAd A  A A @A@. T5Begin by undoing the pushes at the start of switch_toSxAPdddA TimesNewRomanAd A  A A @A@. TSxAPdddA TimesNewRomanAd A  A A @A@. T! 2450 0035 5D 1: popl %ebpSrAPdddACourierAd A  A A @A@. T! 2451 0036 5F popl %ediSrAPdddACourierAd A  A A @A@. T! 2452 0037 5E popl %esiSrAPdddACourierAd A  A A @A@. T 2453SrAPdddACourierAd A  A A @A@. T}SrAPdddACourierAd A  A A @A@. T;The exit code is also atomatically supplied by the compilerSxAPdddA TimesNewRomanAd A  A A @A@. T3Here we are setting p3 (last) to the value of prev.SxAPdddA TimesNewRomanAd A  A A @A@. T}SrAPdddACourierAd A  A A @A@. T 2454 #NO_APPSrAPdddACourierAd A  A A @A@. Tq( 2455 0038 89DA movl %ebx, %edxS>ACourierAd A  A T& 2456 003a 89150000 movl %edx, p3SrAPdddACourierAd A  A A @A@. T 2456 0000SrAPdddACourierAd A  A A @A@. T" 2457 0040 5B popl %ebxSrAPdddACourierAd A  A A @A@. T 2458 0041 C3 retSrAPdddACourierAd A  A A @A@. Tz@The __switch_to function saves and restores some additional regsSA PA!8@ TimesNewRomanT T&SACourierTW1676 void __switch_to(struct task_struct *prev_p, SACourierTE struct task_struct *next_p)SACourierT+677 {SACourierT_9678 struct thread_struct *prev = &prev_p->thread,SACourierTc=679 *next = &next_p->thread;SACourierTiC680 struct tss_struct *tss = init_tss + smp_processor_id();SACourierT*681 SACourierTE682 unlazy_fpu(prev_p);SACourierT*683 SACourierT4684 /*SACourierTa;685 * Reload esp0, LDT and the page table pointer:SACourierT5686 */SACourierTI#687 tss->esp0 = next->esp0;SACourierT*688 SACourierT4689 /*SACourierTkE690 * Save away %fs and %gs. No need to save %es and %ds, asSACourierTqK691 * those are always kernel segments while inside the kernel.SACourierT5692 */SACourierTC693 asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));A8CourierA8CCourierThB694 asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));SACourierT*695 SACourierT4696 /*SACourierTI#697 * Restore %fs and %gs.SACourierT5698 */SACourierTL&699 loadsegment(fs, next->fs);SACourierTL&700 loadsegment(gs, next->gs);SACourierT*701 SACourierT&SACourierTpJFinish by reloading debug registers and I/O permission bitmap if required.SACourierJGeneric PrinterSGENPRT PostScriptH`Tl`Tld,,lprdefault_queueSGENPRT7 UO/H/V88/p?m/=U'2P  #U'y0?%B'B'B*'B?' EI$ BK' EI$ BW' EI$ Bc' EI$ Bo' EI$ B{' EI$  B ' Ey!  B ' Ey!  B ' Ey!  B ' Ey!  B ' Ey! B' Ey! B' Ey! B' Ep B' Ep B' E@  B' Ey! B 'B ' B,'B'B'B'B'B'B'Bv' B' B'  B ' !B!'"B"'#Br#'$BX$' %,U6''' F @' Ы>/=U'2p  _U'y0?,B' &B ' 'B' EI$ (B$' EI$ )B0' EI$ *B<' EI$ +BH' ,BT' EI$ -B`' .Bl '/BR '0B8 '1B ' 2B* ' 3B6'4B'5B'6B'7B' 8B' 9B' :B' ;B'<B'=B'>B'?B'@@B'ABB' BCB'CDB'DEB?'EFB'FGB 'GHB|!'HIB;"'IJB"'JKB#'KLBx$'LMB7%'MNB%'NOB&'OPBt''PQB3('QR,U6''' F @' }/=U'2P  ¸U'y0?1B'RSB' STB' TUB'UVB'VWB' WXB' XYB' YZB'Z[B'[\B '\]B ']^B '^_Bg '_`BM '`aB3'abB'bcB' cdB ' deB' efB#' fgB/'ghB'hiB'ijB'jkB'klB'lmB'mnBy' noB' opB' pqB' qrB'rsB'stBu 'tuB[!'uvBA"'vwB'#'wxB $'xyB$'yzB%'z{B&'{|B'' |}B(' }~B)' ~B*'B+'B,' B-' ,U6''' F @' %/=U'2p  U'y0?B'B' B!' EI$ B-' Ey! B9' Ey! BE' EI$ BQ' EI$ B]'E!Bu ' E! B 'E!B ' E! B ' E! B' EI$ B' B' B'B'B'B'Bm'BS'B9'B'B'B'B'B'Bi'BO'B5 'B!',U6''' F @' %/=U'2P  ªU'y0?.B'B' B' B'B'B'B'B|'Bb'BH 'B. 'B 'B 'B 'B 'B'B'Bx'B^'BD'B*'B'B'B'B'B'B'Bt'BZ'B@'B&'B 'B'B'B'B 'B!'Bp"'BV#'B<$'B"%'B&'B&'B''B('B)',U6''' F @' %:/=U'2p  U'y0?!B'B'B'B'B'B~'Bd'BJ'B0'B' B" 'B7 'BL ' E`$ BX ' E`$ Bd ' E`$ Bp'E`$B' EI$ B' B'B'Bl'BR'B8'B'B'B'B'B'B'Bh'BN'B4'B ' EI$ ,U6''' F @' Н%y/=U'2P  PU'y0?B' B ' EI$ B'B'B'B'B'B'B|'Bb'BH 'B. 'B 'B 'B 'B 'B' B' Bx' B^' BD' B*'B'B'B' B' B' B' EI$  ,U6''' F @' '%/=U'2p  U'y0?/B' B' B!' EI$ B-' EI$ B9' EI$ BE' EI$ BQ'B7'B'B 'B 'B ' B '!B '"B '#Bg'$BM'&B''B'(B' )B'!*B' "+B'#-B' $.B' %/B' &0B''1B'(2B')3B'*4B'+5Bw',6B] '-7BC!'.8B)"'/9B#'0:B#'1;B$'2<B%'3=B&'4>B''5?Bs('6@BY)'7AB?*'8BB%+'9CB ,':DB,' ;E,U6''' F @' %/=U'2P  ¦U'y0?!B'<FB' =GB!' >HB-' ?IB9' @JBE' AKBQ' BLB]' CMBi' DNBu 'EOB[ 'FPBA 'GQB' 'HRB 'ISB 'JTB'KUB'LVB'MWB'NXBq'OYBW'PZB='Q[B#'R\B ' S]B' T^B!' U_B-'V`B'WaB'XbB'YcB'ZdB'[eB' \f,U6''' F @' %6/=U'2p  ¢U'y0?B' ]gB ' ^hB' _iB$' `jB0'akB'blB'cmB'dnB'eoB'fpB 'gqBz ' hrB ' isB ' jtB 'kuB'lvBj'mwBP'nxB6'oyB'pz,U6''' F @' %u/=U'2P  ;U'R&?(B'q{B'r|B*' s}B6' t~BB'uB('vB'wB'xB'yB'zB '{B '|BX '}B> '~B$' B0' B<' @BH' EI$ BT'B:'B 'B'B'B'B'B'B'Bj'BP'B6'B'B'B'B'B 'B!'B"'Bf#'BL$'B2%'bU+'' |' ?GQ|' ?4P'P'P' ,U6''' F @' }%Դ/=U'2p  0U'y0?#B' B ' B' E[$ B$' E[$ B0' E[$ B<' E[$ BH' E[$ BT' E[$ B`' E[$ Bl ' E[$ Bx ' E[$ B 'Bj 'BP 'B6'B'B'B'B'B'B'B' B' B' B'B'Bp'BV'B<'B"' E[$ B.' B:' E[$ BF' E[$ BR ' E[$ B^!'E[$,U6''' F @' %/=U'2P  ¬U'y0?,B'B'B' B' B' B' B' B' E[$ B'B'B 'B 'B 'B 'Bx 'B^'BD' BP' E[$ B\' E[$ Bh' E[$ Bt' E[$ B' E[$ B'Br'BX'B>'B$' B0' B<' BH' BT'B:'B 'B 'B 'B!' B"' B#'B$'B%'B&'B''Bh('BN)',U6''' F @' %2/=U'2p  ’U'y0? B' B ' B'B'B'B'B'B'B|'Bb'BH 'B. 'B 'B 'B 'B 'B'B'Bx'B^'B*'B'  B' B' B' B' B'B'B'Bf'BL'B2',U6''' F @' lZRoot Entry ®`VCompObj<Ole persist elements" SfxDocumentInfo uBasicManager2 4StarBASIC SfxWindowsCSwNumRules{StandardjSfxStyleSheetsdSummaryInformation( *0SwPageStyleSheets$ /StarWriterDocument&