The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/swtch.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1990 The Regents of the University of California.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * William Jolitz.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  * $FreeBSD: src/sys/i386/i386/swtch.s,v 1.41.2.1 1999/09/05 08:11:17 peter Exp $
   37  */
   38 
   39 #include "apm.h"
   40 #include "npx.h"
   41 #include "opt_user_ldt.h"
   42 
   43 #include <sys/rtprio.h>
   44 
   45 #include <machine/asmacros.h>
   46 #include <machine/spl.h>
   47 
   48 #include "assym.s"
   49 
   50 
   51 /*****************************************************************************/
   52 /* Scheduling                                                                */
   53 /*****************************************************************************/
   54 
   55 /*
   56  * The following primitives manipulate the run queues.
   57  * _whichqs tells which of the 32 queues _qs
   58  * have processes in them.  setrunqueue puts processes into queues, Remrq
   59  * removes them from queues.  The running process is on no queue,
   60  * other processes are on a queue related to p->p_priority, divided by 4
   61  * actually to shrink the 0-127 range of priorities into the 32 available
   62  * queues.
   63  */
   64         .data
   65         .globl  _curpcb
   66 _curpcb:        .long   0                       /* pointer to curproc's PCB area */
   67 _whichqs:       .long   0                       /* which run queues have data */
   68 _whichrtqs:     .long   0                       /* which realtime run queues have data */
   69 _whichidqs:     .long   0                       /* which idletime run queues have data */
   70 
   71         .globl  _qs,_cnt,_panic
   72 
   73         .globl  _want_resched
   74 _want_resched:  .long   0                       /* we need to re-run the scheduler */
   75 
   76         .text
   77 /*
   78  * setrunqueue(p)
   79  *
   80  * Call should be made at spl6(), and p->p_stat should be SRUN
   81  */
   82 ENTRY(setrunqueue)
   83         movl    4(%esp),%eax
   84 #ifdef DIAGNOSTIC
   85         cmpb    $SRUN,P_STAT(%eax)
   86         je      set1
   87         pushl   $set2
   88         call    _panic
   89 set1:
   90 #endif
   91         cmpw    $RTP_PRIO_NORMAL,P_RTPRIO_TYPE(%eax) /* normal priority process? */
   92         je      set_nort
   93 
   94         movzwl  P_RTPRIO_PRIO(%eax),%edx
   95 
   96         cmpw    $RTP_PRIO_REALTIME,P_RTPRIO_TYPE(%eax) /* realtime priority? */
   97         jne     set_id                          /* must be idle priority */
   98         
   99 set_rt:
  100         btsl    %edx,_whichrtqs                 /* set q full bit */
  101         shll    $3,%edx
  102         addl    $_rtqs,%edx                     /* locate q hdr */
  103         movl    %edx,P_FORW(%eax)               /* link process on tail of q */
  104         movl    P_BACK(%edx),%ecx
  105         movl    %ecx,P_BACK(%eax)
  106         movl    %eax,P_BACK(%edx)
  107         movl    %eax,P_FORW(%ecx)
  108         ret
  109 
  110 set_id: 
  111         btsl    %edx,_whichidqs                 /* set q full bit */
  112         shll    $3,%edx
  113         addl    $_idqs,%edx                     /* locate q hdr */
  114         movl    %edx,P_FORW(%eax)               /* link process on tail of q */
  115         movl    P_BACK(%edx),%ecx
  116         movl    %ecx,P_BACK(%eax)
  117         movl    %eax,P_BACK(%edx)
  118         movl    %eax,P_FORW(%ecx)
  119         ret
  120 
  121 set_nort:                                       /*  Normal (RTOFF) code */
  122         movzbl  P_PRI(%eax),%edx
  123         shrl    $2,%edx
  124         btsl    %edx,_whichqs                   /* set q full bit */
  125         shll    $3,%edx
  126         addl    $_qs,%edx                       /* locate q hdr */
  127         movl    %edx,P_FORW(%eax)               /* link process on tail of q */
  128         movl    P_BACK(%edx),%ecx
  129         movl    %ecx,P_BACK(%eax)
  130         movl    %eax,P_BACK(%edx)
  131         movl    %eax,P_FORW(%ecx)
  132         ret
  133 
  134 set2:   .asciz  "setrunqueue"
  135 
  136 /*
  137  * Remrq(p)
  138  *
  139  * Call should be made at spl6().
  140  */
  141 ENTRY(remrq)
  142         movl    4(%esp),%eax
  143         cmpw    $RTP_PRIO_NORMAL,P_RTPRIO_TYPE(%eax) /* normal priority process? */
  144         je      rem_nort
  145 
  146         movzwl  P_RTPRIO_PRIO(%eax),%edx
  147 
  148         cmpw    $RTP_PRIO_REALTIME,P_RTPRIO_TYPE(%eax) /* normal priority process? */
  149         jne     rem_id
  150                 
  151         btrl    %edx,_whichrtqs                 /* clear full bit, panic if clear already */
  152         jb      rem1rt
  153         pushl   $rem3rt
  154         call    _panic
  155 rem1rt:
  156         pushl   %edx
  157         movl    P_FORW(%eax),%ecx               /* unlink process */
  158         movl    P_BACK(%eax),%edx
  159         movl    %edx,P_BACK(%ecx)
  160         movl    P_BACK(%eax),%ecx
  161         movl    P_FORW(%eax),%edx
  162         movl    %edx,P_FORW(%ecx)
  163         popl    %edx
  164         movl    $_rtqs,%ecx
  165         shll    $3,%edx
  166         addl    %edx,%ecx
  167         cmpl    P_FORW(%ecx),%ecx               /* q still has something? */
  168         je      rem2rt
  169         shrl    $3,%edx                         /* yes, set bit as still full */
  170         btsl    %edx,_whichrtqs
  171 rem2rt:
  172         ret
  173 rem_id:
  174         btrl    %edx,_whichidqs                 /* clear full bit, panic if clear already */
  175         jb      rem1id
  176         pushl   $rem3id
  177         call    _panic
  178 rem1id:
  179         pushl   %edx
  180         movl    P_FORW(%eax),%ecx               /* unlink process */
  181         movl    P_BACK(%eax),%edx
  182         movl    %edx,P_BACK(%ecx)
  183         movl    P_BACK(%eax),%ecx
  184         movl    P_FORW(%eax),%edx
  185         movl    %edx,P_FORW(%ecx)
  186         popl    %edx
  187         movl    $_idqs,%ecx
  188         shll    $3,%edx
  189         addl    %edx,%ecx
  190         cmpl    P_FORW(%ecx),%ecx               /* q still has something? */
  191         je      rem2id
  192         shrl    $3,%edx                         /* yes, set bit as still full */
  193         btsl    %edx,_whichidqs
  194 rem2id:
  195         ret
  196 
  197 rem_nort:     
  198         movzbl  P_PRI(%eax),%edx
  199         shrl    $2,%edx
  200         btrl    %edx,_whichqs                   /* clear full bit, panic if clear already */
  201         jb      rem1
  202         pushl   $rem3
  203         call    _panic
  204 rem1:
  205         pushl   %edx
  206         movl    P_FORW(%eax),%ecx               /* unlink process */
  207         movl    P_BACK(%eax),%edx
  208         movl    %edx,P_BACK(%ecx)
  209         movl    P_BACK(%eax),%ecx
  210         movl    P_FORW(%eax),%edx
  211         movl    %edx,P_FORW(%ecx)
  212         popl    %edx
  213         movl    $_qs,%ecx
  214         shll    $3,%edx
  215         addl    %edx,%ecx
  216         cmpl    P_FORW(%ecx),%ecx               /* q still has something? */
  217         je      rem2
  218         shrl    $3,%edx                         /* yes, set bit as still full */
  219         btsl    %edx,_whichqs
  220 rem2:
  221         ret
  222 
  223 rem3:   .asciz  "remrq"
  224 rem3rt: .asciz  "remrq.rt"
  225 rem3id: .asciz  "remrq.id"
  226 
  227 /*
  228  * When no processes are on the runq, cpu_switch() branches to _idle
  229  * to wait for something to come ready.
  230  */
  231         ALIGN_TEXT
  232 _idle:
  233         xorl    %ebp,%ebp
  234         movl    $tmpstk,%esp
  235         movl    _IdlePTD,%ecx
  236         movl    %ecx,%cr3
  237         sti
  238 
  239         /*
  240          * XXX callers of cpu_switch() do a bogus splclock().  Locking should
  241          * be left to cpu_switch().
  242          */
  243         movl    $SWI_AST_MASK,_cpl
  244         testl   $~SWI_AST_MASK,_ipending
  245         je      idle_loop
  246         call    _splz
  247 
  248         ALIGN_TEXT
  249 idle_loop:
  250         cli
  251         movb    $1,_intr_nesting_level          /* charge Intr if we leave */
  252         cmpl    $0,_whichrtqs                   /* real-time queue */
  253         CROSSJUMP(jne, sw1a, je)
  254         cmpl    $0,_whichqs                     /* normal queue */
  255         CROSSJUMP(jne, nortqr, je)
  256         cmpl    $0,_whichidqs                   /* 'idle' queue */
  257         CROSSJUMP(jne, idqr, je)
  258         movb    $0,_intr_nesting_level          /* charge Idle for this loop */
  259         call    _vm_page_zero_idle
  260         testl   %eax, %eax
  261         jnz     idle_loop
  262         sti
  263 #if NAPM > 0 && defined(APM_IDLE_CPU)
  264         call    _apm_cpu_idle
  265         call    _apm_cpu_busy
  266 #else
  267         hlt                                     /* wait for interrupt */
  268 #endif
  269         jmp     idle_loop
  270 
  271 CROSSJUMPTARGET(_idle)
  272 
  273 /*
  274  * cpu_switch()
  275  */
  276 ENTRY(cpu_switch)
  277         /* switch to new process. first, save context as needed */
  278         movl    _curproc,%ecx
  279 
  280         /* if no process to save, don't bother */
  281         testl   %ecx,%ecx
  282         je      sw1
  283 
  284         movl    P_ADDR(%ecx),%ecx
  285 
  286         movl    (%esp),%eax                     /* Hardware registers */
  287         movl    %eax,PCB_EIP(%ecx)
  288         movl    %ebx,PCB_EBX(%ecx)
  289         movl    %esp,PCB_ESP(%ecx)
  290         movl    %ebp,PCB_EBP(%ecx)
  291         movl    %esi,PCB_ESI(%ecx)
  292         movl    %edi,PCB_EDI(%ecx)
  293 
  294 #if NNPX > 0
  295         /* have we used fp, and need a save? */
  296         mov     _curproc,%eax
  297         cmp     %eax,_npxproc
  298         jne     1f
  299         addl    $PCB_SAVEFPU,%ecx               /* h/w bugs make saving complicated */
  300         pushl   %ecx
  301         call    _npxsave                        /* do it in a big C function */
  302         popl    %eax
  303 1:
  304 #endif  /* NNPX > 0 */
  305 
  306         movb    $1,_intr_nesting_level          /* charge Intr, not Sys/Idle */
  307 
  308         movl    $0,_curproc                     /* out of process */
  309 
  310         /* save is done, now choose a new process or idle */
  311 sw1:
  312         cli
  313 sw1a:
  314         movl    _whichrtqs,%edi                 /* pick next p. from rtqs */
  315         testl   %edi,%edi
  316         jz      nortqr                          /* no realtime procs */
  317 
  318         /* XXX - bsf is sloow */
  319         bsfl    %edi,%ebx                       /* find a full q */
  320         jz      nortqr                          /* no proc on rt q - try normal ... */
  321 
  322         /* XX update whichqs? */
  323         btrl    %ebx,%edi                       /* clear q full status */
  324         leal    _rtqs(,%ebx,8),%eax             /* select q */
  325         movl    %eax,%esi
  326 
  327         movl    P_FORW(%eax),%ecx               /* unlink from front of process q */
  328         movl    P_FORW(%ecx),%edx
  329         movl    %edx,P_FORW(%eax)
  330         movl    P_BACK(%ecx),%eax
  331         movl    %eax,P_BACK(%edx)
  332 
  333         cmpl    P_FORW(%ecx),%esi               /* q empty */
  334         je      rt3
  335         btsl    %ebx,%edi                       /* nope, set to indicate not empty */
  336 rt3:
  337         movl    %edi,_whichrtqs                 /* update q status */
  338         jmp     swtch_com
  339 
  340         /* old sw1a */
  341 /* Normal process priority's */
  342 nortqr:
  343         movl    _whichqs,%edi
  344 2:
  345         /* XXX - bsf is sloow */
  346         bsfl    %edi,%ebx                       /* find a full q */
  347         jz      idqr                            /* if none, idle */
  348 
  349         /* XX update whichqs? */
  350         btrl    %ebx,%edi                       /* clear q full status */
  351         leal    _qs(,%ebx,8),%eax               /* select q */
  352         movl    %eax,%esi
  353 
  354         movl    P_FORW(%eax),%ecx               /* unlink from front of process q */
  355         movl    P_FORW(%ecx),%edx
  356         movl    %edx,P_FORW(%eax)
  357         movl    P_BACK(%ecx),%eax
  358         movl    %eax,P_BACK(%edx)
  359 
  360         cmpl    P_FORW(%ecx),%esi               /* q empty */
  361         je      3f
  362         btsl    %ebx,%edi                       /* nope, set to indicate not empty */
  363 3:
  364         movl    %edi,_whichqs                   /* update q status */
  365         jmp     swtch_com
  366 
  367 idqr: /* was sw1a */
  368         movl    _whichidqs,%edi                 /* pick next p. from idqs */
  369 
  370         /* XXX - bsf is sloow */
  371         bsfl    %edi,%ebx                       /* find a full q */
  372         CROSSJUMP(je, _idle, jne)               /* if no proc, idle */
  373 
  374         /* XX update whichqs? */
  375         btrl    %ebx,%edi                       /* clear q full status */
  376         leal    _idqs(,%ebx,8),%eax             /* select q */
  377         movl    %eax,%esi
  378 
  379         movl    P_FORW(%eax),%ecx               /* unlink from front of process q */
  380         movl    P_FORW(%ecx),%edx
  381         movl    %edx,P_FORW(%eax)
  382         movl    P_BACK(%ecx),%eax
  383         movl    %eax,P_BACK(%edx)
  384 
  385         cmpl    P_FORW(%ecx),%esi               /* q empty */
  386         je      id3
  387         btsl    %ebx,%edi                       /* nope, set to indicate not empty */
  388 id3:
  389         movl    %edi,_whichidqs                 /* update q status */
  390 
  391 swtch_com:
  392         movl    $0,%eax
  393         movl    %eax,_want_resched
  394 
  395 #ifdef  DIAGNOSTIC
  396         cmpl    %eax,P_WCHAN(%ecx)
  397         jne     badsw
  398         cmpb    $SRUN,P_STAT(%ecx)
  399         jne     badsw
  400 #endif
  401 
  402         movl    %eax,P_BACK(%ecx)               /* isolate process to run */
  403         movl    P_ADDR(%ecx),%edx
  404         movl    PCB_CR3(%edx),%ebx
  405 
  406         /* switch address space */
  407         movl    %ebx,%cr3
  408 
  409         /* restore context */
  410         movl    PCB_EBX(%edx),%ebx
  411         movl    PCB_ESP(%edx),%esp
  412         movl    PCB_EBP(%edx),%ebp
  413         movl    PCB_ESI(%edx),%esi
  414         movl    PCB_EDI(%edx),%edi
  415         movl    PCB_EIP(%edx),%eax
  416         movl    %eax,(%esp)
  417 
  418         movl    %edx,_curpcb
  419         movl    %ecx,_curproc                   /* into next process */
  420         movb    $0,_intr_nesting_level
  421 
  422 #ifdef  USER_LDT
  423         cmpl    $0, PCB_USERLDT(%edx)
  424         jnz     1f
  425         movl    __default_ldt,%eax
  426         cmpl    _currentldt,%eax
  427         je      2f
  428         lldt    __default_ldt
  429         movl    %eax,_currentldt
  430         jmp     2f
  431 1:      pushl   %edx
  432         call    _set_user_ldt
  433         popl    %edx
  434 2:
  435 #endif
  436 
  437         sti
  438         ret
  439 
  440 CROSSJUMPTARGET(idqr)
  441 CROSSJUMPTARGET(nortqr)
  442 CROSSJUMPTARGET(sw1a)
  443 
  444 badsw:
  445         pushl   $sw0
  446         call    _panic
  447 
  448 sw0:    .asciz  "cpu_switch"
  449 
  450 /*
  451  * savectx(pcb)
  452  * Update pcb, saving current processor state.
  453  */
  454 ENTRY(savectx)
  455         /* fetch PCB */
  456         movl    4(%esp),%ecx
  457 
  458         /* caller's return address - child won't execute this routine */
  459         movl    (%esp),%eax
  460         movl    %eax,PCB_EIP(%ecx)
  461 
  462         movl    %ebx,PCB_EBX(%ecx)
  463         movl    %esp,PCB_ESP(%ecx)
  464         movl    %ebp,PCB_EBP(%ecx)
  465         movl    %esi,PCB_ESI(%ecx)
  466         movl    %edi,PCB_EDI(%ecx)
  467 
  468 #if NNPX > 0
  469         /*
  470          * If npxproc == NULL, then the npx h/w state is irrelevant and the
  471          * state had better already be in the pcb.  This is true for forks
  472          * but not for dumps (the old book-keeping with FP flags in the pcb
  473          * always lost for dumps because the dump pcb has 0 flags).
  474          *
  475          * If npxproc != NULL, then we have to save the npx h/w state to
  476          * npxproc's pcb and copy it to the requested pcb, or save to the
  477          * requested pcb and reload.  Copying is easier because we would
  478          * have to handle h/w bugs for reloading.  We used to lose the
  479          * parent's npx state for forks by forgetting to reload.
  480          */
  481         mov     _npxproc,%eax
  482         testl   %eax,%eax
  483         je      1f
  484 
  485         pushl   %ecx
  486         movl    P_ADDR(%eax),%eax
  487         leal    PCB_SAVEFPU(%eax),%eax
  488         pushl   %eax
  489         pushl   %eax
  490         call    _npxsave
  491         addl    $4,%esp
  492         popl    %eax
  493         popl    %ecx
  494 
  495         pushl   $PCB_SAVEFPU_SIZE
  496         leal    PCB_SAVEFPU(%ecx),%ecx
  497         pushl   %ecx
  498         pushl   %eax
  499         call    _bcopy
  500         addl    $12,%esp
  501 #endif  /* NNPX > 0 */
  502 
  503 1:
  504         ret

Cache object: e7bebf09d90fc73af29301d463f107b8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.