Annotation of XNU/osfmk/kern/thread_swap.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /*
        !            26:  * Mach Operating System
        !            27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
        !            28:  * All Rights Reserved.
        !            29:  * 
        !            30:  * Permission to use, copy, modify and distribute this software and its
        !            31:  * documentation is hereby granted, provided that both the copyright
        !            32:  * notice and this permission notice appear in all copies of the
        !            33:  * software, derivative works or modified versions, and any portions
        !            34:  * thereof, and that both notices appear in supporting documentation.
        !            35:  * 
        !            36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            39:  * 
        !            40:  * Carnegie Mellon requests users of this software to return to
        !            41:  * 
        !            42:  *  Software Distribution Coordinator  or  [email protected]
        !            43:  *  School of Computer Science
        !            44:  *  Carnegie Mellon University
        !            45:  *  Pittsburgh PA 15213-3890
        !            46:  * 
        !            47:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            48:  * the rights to redistribute these changes.
        !            49:  */
        !            50: /*
        !            51:  */
        !            52: /*
        !            53:  *
        !            54:  *     File:   kern/thread_swap.c
        !            55:  *     Author: Avadis Tevanian, Jr.
        !            56:  *     Date:   1987
        !            57:  *
        !            58:  *     Mach thread swapper:
        !            59:  *             Find idle threads to swap, freeing up kernel stack resources
        !            60:  *             at the expense of allowing them to execute.
        !            61:  *
        !            62:  *             Swap in threads that need to be run.  This is done here
        !            63:  *             by the swapper thread since it cannot be done (in general)
        !            64:  *             when the kernel tries to place a thread on a run queue.
        !            65:  *
        !            66:  *     Note: The act of swapping a thread in Mach does not mean that
        !            67:  *     its memory gets forcibly swapped to secondary storage.  The memory
        !            68:  *     for the task corresponding to a swapped thread is paged out
        !            69:  *     through the normal paging mechanism.
        !            70:  *
        !            71:  */
        !            72: #if 1
        !            73: 
        !            74: #include <kern/thread.h>
        !            75: #include <kern/lock.h>
        !            76: #include <vm/vm_map.h>
        !            77: #include <vm/vm_kern.h>
        !            78: #include <mach/vm_param.h>
        !            79: #include <kern/sched_prim.h>
        !            80: #include <kern/sf.h>
        !            81: #include <kern/processor.h>
        !            82: #include <kern/thread_swap.h>
        !            83: #include <kern/spl.h>          /* for splsched */
        !            84: #include <kern/misc_protos.h>
        !            85: #include <kern/counters.h>
        !            86: #include <mach/policy.h>
        !            87: 
        !            88: queue_head_t           swapin_queue;
        !            89: decl_simple_lock_data(,        swapper_lock_data)
        !            90: 
        !            91: #define swapper_lock()         simple_lock(&swapper_lock_data)
        !            92: #define swapper_unlock()       simple_unlock(&swapper_lock_data)
        !            93: 
        !            94: mach_counter_t c_swapin_thread_block;
        !            95: 
        !            96: /*
        !            97:  *     swapper_init: [exported]
        !            98:  *
        !            99:  *     Initialize the swapper module.
        !           100:  */
        !           101: void swapper_init()
        !           102: {
        !           103:         queue_init(&swapin_queue);
        !           104:         simple_lock_init(&swapper_lock_data, ETAP_THREAD_SWAPPER);
        !           105: }
        !           106: 
        !           107: /*
        !           108:  *     thread_swapin: [exported]
        !           109:  *
        !           110:  *     Place the specified thread in the list of threads to swapin.  It
        !           111:  *     is assumed that the thread is locked, therefore we are at splsched.
        !           112:  *
        !           113:  *     We don't bother with stack_alloc_try to optimize swapin;
        !           114:  *     our callers have already tried that route.
        !           115:  */
        !           116: 
        !           117: void thread_swapin(thread)
        !           118:        thread_t        thread;
        !           119: {
        !           120:        switch (thread->state & TH_STACK_STATE) {
        !           121:        case TH_STACK_HANDOFF:
        !           122:                /*
        !           123:                 *      Swapped out - queue for swapin thread.
        !           124:                 */
        !           125:                thread->state = (thread->state & ~TH_STACK_STATE)
        !           126:                                | TH_STACK_COMING_IN;
        !           127:                swapper_lock();
        !           128:                enqueue_tail(&swapin_queue, (queue_entry_t) thread);
        !           129:                swapper_unlock();
        !           130:                thread_wakeup((event_t) &swapin_queue);
        !           131:                break;
        !           132: 
        !           133:            case TH_STACK_COMING_IN:
        !           134:                /*
        !           135:                 *      Already queued for swapin thread, or being
        !           136:                 *      swapped in.
        !           137:                 */
        !           138:                break;
        !           139: 
        !           140:            default:
        !           141:                /*
        !           142:                 *      Already swapped in.
        !           143:                 */
        !           144:                panic("thread_swapin");
        !           145:        }
        !           146: }
        !           147: 
        !           148: /*
        !           149:  *     thread_doswapin:
        !           150:  *
        !           151:  *     Swapin the specified thread, if it should be runnable, then put
        !           152:  *     it on a run queue.  No locks should be held on entry, as it is
        !           153:  *     likely that this routine will sleep (waiting for stack allocation).
        !           154:  */
        !           155: void thread_doswapin(thread)
        !           156:        register thread_t thread;
        !           157: {
        !           158:        spl_t   s;
        !           159:        vm_offset_t stack;
        !           160: 
        !           161:        /*
        !           162:         * do machdep allocation
        !           163:         */
        !           164: 
        !           165:        /*
        !           166:         *      Allocate the kernel stack.
        !           167:         */
        !           168:        stack = stack_alloc(thread, thread_continue);
        !           169:        assert(stack);
        !           170: 
        !           171:        /*
        !           172:         *      Place on run queue.  
        !           173:         */
        !           174: 
        !           175:        s = splsched();
        !           176:        thread_lock(thread);
        !           177:        thread->state &= ~(TH_STACK_HANDOFF | TH_STACK_COMING_IN);
        !           178:        if (thread->state & TH_RUN)
        !           179:                thread_setrun(thread, TRUE, FALSE);
        !           180:        thread_unlock(thread);
        !           181:        (void) splx(s);
        !           182: }
        !           183: 
        !           184: /*
        !           185:  *     swapin_thread: [exported]
        !           186:  *
        !           187:  *     This procedure executes as a kernel thread.  Threads that need to
        !           188:  *     be swapped in are swapped in by this thread.
        !           189:  */
        !           190: void swapin_thread_continue()
        !           191: {
        !           192:        for (;;) {
        !           193:                register thread_t thread;
        !           194:                spl_t s;
        !           195: 
        !           196:                s = splsched();
        !           197:                swapper_lock();
        !           198: 
        !           199:                while ((thread = (thread_t) dequeue_head(&swapin_queue))
        !           200:                                                        != THREAD_NULL) {
        !           201:                        swapper_unlock();
        !           202:                        (void) splx(s);
        !           203: 
        !           204:                        thread_doswapin(thread);                /* may block */
        !           205: 
        !           206:                        s = splsched();
        !           207:                        swapper_lock();
        !           208:                }
        !           209: 
        !           210:                assert_wait((event_t) &swapin_queue, THREAD_UNINT);
        !           211:                swapper_unlock();
        !           212:                (void) splx(s);
        !           213:                counter(c_swapin_thread_block++);
        !           214: #if 1
        !           215:                thread_block(swapin_thread_continue);
        !           216: #else
        !           217:                thread_block((void (*)(void)) 0);
        !           218: #endif
        !           219:        }
        !           220: }
        !           221: 
        !           222: void swapin_thread()
        !           223: {
        !           224:        stack_privilege(current_thread());
        !           225:        current_thread()->vm_privilege = TRUE;
        !           226: 
        !           227:        swapin_thread_continue();
        !           228:        /*NOTREACHED*/
        !           229: }
        !           230: 
        !           231: #else /* UNUSED CODE FOLLOWS */
        !           232: 
        !           233: #include <kern/thread.h>
        !           234: #include <kern/lock.h>
        !           235: #include <vm/vm_map.h>
        !           236: #include <vm/vm_kern.h>
        !           237: #include <mach/vm_param.h>
        !           238: #include <kern/sched_prim.h>
        !           239: #include <kern/sf.h>
        !           240: #include <kern/processor.h>
        !           241: #include <kern/thread_swap.h>
        !           242: #include <kern/spl.h>          /* for splsched */
        !           243: #include <kern/misc_protos.h>
        !           244: #include <mach/policy.h>
        !           245: 
        !           246: queue_head_t           swapin_queue;
        !           247: decl_simple_lock_data(,swapper_lock)
        !           248: 
        !           249: #define swapper_lock()         simple_lock(&swapper_lock)
        !           250: #define swapper_unlock()       simple_unlock(&swapper_lock)
        !           251: 
        !           252: #define THREAD_SW_DEBUG 1
        !           253: int thread_swap_debug = 0;
        !           254: 
        !           255: /*
        !           256:  * MAXSLP and MAX_SWAP_RATE can be overridden in vm_param.h, or by poking
        !           257:  * the global variable (lower-case) at any time.
        !           258:  *
        !           259:  * MAXSLP is the amount of time a thread will be allowed to sleep
        !           260:  * without being a candidate for idle thread swapping.
        !           261:  *
        !           262:  * MAX_SWAP_RATE is the number of scheduler ticks (see sched_prim.c),
        !           263:  * between periodic scans of the idle thread list. When the pageout
        !           264:  * daemon detects a severe page shortage, this rate is ignored. A 
        !           265:  * scheduler tick is usually 1 second.
        !           266:  */
        !           267: #ifndef MAXSLP
        !           268: #define MAXSLP 10
        !           269: #endif
        !           270: 
        !           271: int    maxslp = MAXSLP;
        !           272: 
        !           273: #ifndef MAX_SWAP_RATE
        !           274: #define MAX_SWAP_RATE  60
        !           275: #endif
        !           276: 
        !           277: int    max_swap_rate = MAX_SWAP_RATE;
        !           278: 
        !           279: /* should we unwire the kernel stack when a thread is swapped out ? */
        !           280: #ifdef HP700___  /* CHECKME! Is this true anymore??  From Cambridge branch */
        !           281: /*
        !           282:  * On HP/PA, kernel stacks are ghost pages that are mapped at their
        !           283:  * physical address (physical addr == virtual address). They're not
        !           284:  * on any page list or VM object, so they can't be paged out.
        !           285:  */
        !           286: boolean_t thread_swap_unwire_stack = FALSE;
        !           287: #else  /* HP700 */
        !           288: boolean_t thread_swap_unwire_stack = TRUE;
        !           289: #endif /* HP700 */
        !           290: 
        !           291: #if    THREAD_SWAP_UNWIRE_USER_STACK
        !           292: boolean_t thread_swap_unwire_user_stack = TRUE;
        !           293: #else  /* THREAD_SWAP_UNWIRE_USER_STACK */
        !           294: #define thread_swap_unwire_user_stack  FALSE
        !           295: #endif /* THREAD_SWAP_UNWIRE_USER_STACK */
        !           296: 
        !           297: /*
        !           298:  *     thread_swapper_init: [exported]
        !           299:  *
        !           300:  *     Initialize the swapper module.
        !           301:  */
        !           302: void thread_swapper_init(void)
        !           303: {
        !           304:        queue_init(&swapin_queue);
        !           305:        simple_lock_init(&swapper_lock, ETAP_THREAD_SWAPPER);
        !           306: }
        !           307: 
        !           308: /*
        !           309:  *     thread_swapin: [exported]
        !           310:  *
        !           311:  *     Place the specified thread in the list of threads to swapin.  If
        !           312:  *     thr_act is associated with a thread, the thread is locked; if not,
        !           313:  *     the thr_act itself (i.e., its act_lock()) is locked.  Since
        !           314:  *     swapper_lock() must be taken at splsched(), we go to splsched()
        !           315:  *     ourself to cover the latter case.  The make_unswappable argument
        !           316:  *     is used to ask swapin_thread to make thread unswappable.
        !           317:  *
        !           318:  *     The naked references to thr_act->thread here are safe purely based
        !           319:  *     on the assumption that only an activation itself can remove itself
        !           320:  *     from an RPC chain.  Since its thread is "swapped out", the activation
        !           321:  *     cannot be running.  Similarly, the reference to thread->top_act
        !           322:  *     in calls to this function from scheduler code is safe purely because
        !           323:  *     an RPC chain can change only under its own steam (i.e., if the
        !           324:  *     associated thread is running).
        !           325:  *
        !           326:  *     XXX - Shuttle cloning would break the above assumptions.
        !           327:  */
        !           328: 
        !           329: void thread_swapin(
        !           330:        thread_act_t    thr_act,
        !           331:        boolean_t       make_unswappable)
        !           332: {
        !           333:        spl_t           s;
        !           334: 
        !           335:        switch (thr_act->swap_state & TH_SW_STATE) {
        !           336:            case TH_SW_OUT:
        !           337:                /*
        !           338:                 *      Swapped out - queue for swapin thread
        !           339:                 */
        !           340:                thr_act->swap_state = TH_SW_COMING_IN;
        !           341:                s = splsched();
        !           342:                swapper_lock();
        !           343:                queue_enter(&swapin_queue, thr_act, thread_act_t, swap_queue);
        !           344:                swapper_unlock();
        !           345:                thread_wakeup((event_t) &swapin_queue);
        !           346:                splx(s);
        !           347:                break;
        !           348: 
        !           349:            case TH_SW_GOING_OUT:
        !           350:                /*
        !           351:                 *      Being swapped out - wait until swapped out,
        !           352:                 *      then queue for swapin thread (in thread_swapout).
        !           353:                 */
        !           354:                thr_act->swap_state = TH_SW_WANT_IN;
        !           355:                break;
        !           356: 
        !           357:            case TH_SW_WANT_IN:
        !           358:            case TH_SW_COMING_IN:
        !           359:                /*
        !           360:                 *      Already queued for swapin thread, or being
        !           361:                 *      swapped in
        !           362:                 */
        !           363:                break;
        !           364: 
        !           365:            default:
        !           366:                /*
        !           367:                 *      Swapped in or unswappable
        !           368:                 */
        !           369:                panic("thread_swapin");
        !           370:        }
        !           371: 
        !           372:        /*
        !           373:         *      Set make unswappable flag if asked to.  swapin thread
        !           374:         *      will make thread unswappable.
        !           375:         */
        !           376:        if (make_unswappable)
        !           377:                thr_act->swap_state |= TH_SW_MAKE_UNSWAPPABLE;
        !           378: }
        !           379: 
        !           380: /*
        !           381:  *     thread_swapin_blocking: [exported]
        !           382:  *
        !           383:  *     Mimic thread_swapin(), but block if swapin of our target thread
        !           384:  *     has already been initiated, and call thread_doswapin() directly
        !           385:  *     (instead of via swapin thread) if we initiate it ourself.
        !           386:  *
        !           387:  *     Locking: if thr_act is on an RPC chain, the rpc_lock() for the
        !           388:  *     attached shuttle is held; otherwise both the act_lock() for
        !           389:  *     thr_act plus the ip_lock() for its thread_pool port are held.
        !           390:  *     NB:  if thr_act is attached to a thread, thread_lock() controls
        !           391:  *     access to thr_act's swap_state.
        !           392:  */
        !           393: boolean_t thread_swapin_blocking(
        !           394:        thread_act_t    thr_act)
        !           395: {
        !           396:        spl_t           s;
        !           397:        thread_t        thread, othread;
        !           398: 
        !           399: #define lock_swap_state(thr_act)               \
        !           400: MACRO_BEGIN                                    \
        !           401:        if (thr_act->thread) {                  \
        !           402:                s = splsched();                 \
        !           403:                thread_lock(thr_act->thread);   \
        !           404:        }                                       \
        !           405: MACRO_END
        !           406: 
        !           407: #define unlock_swap_state(thr_act)             \
        !           408: MACRO_BEGIN                                    \
        !           409:        if (thr_act->thread) {                  \
        !           410:                thread_unlock(thr_act->thread); \
        !           411:                splx(s);                        \
        !           412:        }                                       \
        !           413: MACRO_END
        !           414: 
        !           415:        for (thread = thr_act->thread; ; ) {
        !           416:                lock_swap_state(thr_act);
        !           417:                switch (thr_act->swap_state & TH_SW_STATE) {
        !           418:                case TH_SW_OUT:
        !           419:                        /*
        !           420:                         * Swapped all the way out -- start it back in.
        !           421:                         */
        !           422:                        thr_act->swap_state = TH_SW_COMING_IN;
        !           423:                        unlock_swap_state(thr_act);
        !           424:                        if (thread)
        !           425:                                rpc_unlock(thread);
        !           426:                        else {
        !           427:                                ip_unlock(thr_act->pool_port);
        !           428:                                act_unlock(thr_act);
        !           429:                        }
        !           430:                        thread_doswapin(thr_act);
        !           431:                relock:
        !           432:                        othread = thread;
        !           433:                        thread = act_lock_thread(thr_act);
        !           434:                        /*
        !           435:                         * We may resume with a shuttle attached
        !           436:                         * after blocking with no shuttle attached,
        !           437:                         * but should never move between shuttles.
        !           438:                         */
        !           439:                        if (othread && thread != othread)
        !           440:                                panic("thread_swapin_blocking: act moved");
        !           441:                        if (othread) {
        !           442:                                /*
        !           443:                                 * XXX - don't care about this ip_lock (taken
        !           444:                                 * by act_lock_thread() if pool_port non-null)
        !           445:                                 */
        !           446:                                if (thr_act->pool_port)
        !           447:                                        ip_unlock(thr_act->pool_port);
        !           448:                                act_unlock(thr_act);
        !           449:                        }
        !           450:                        else if (thread) {
        !           451:                                /*
        !           452:                                 * XXX - don't care about this rpc_lock (taken
        !           453:                                 * by act_lock_thread() if thread non-null)
        !           454:                                 */
        !           455:                                rpc_unlock(thr_act->thread);
        !           456:                        }
        !           457:                        break;
        !           458: 
        !           459:                case TH_SW_GOING_OUT:
        !           460:                        /*
        !           461:                         * Not out yet -- have to wait till it is, then queue
        !           462:                         * it for swapin.
        !           463:                         */
        !           464:                        thr_act->swap_state = TH_SW_WANT_IN;
        !           465: 
        !           466:                        /* fall-through */
        !           467: 
        !           468:                case TH_SW_WANT_IN:
        !           469:                case TH_SW_COMING_IN:
        !           470:                        /*
        !           471:                         * On its way back -- wait for it to get here.
        !           472:                         */
        !           473:                        assert_wait((event_t)&thr_act->swap_state, THREAD_UNINT);
        !           474:                        unlock_swap_state(thr_act);
        !           475:                        if (thread)
        !           476:                                rpc_unlock(thread);
        !           477:                        else {
        !           478:                                ip_unlock(thr_act->pool_port);
        !           479:                                act_unlock(thr_act);
        !           480:                        }
        !           481:                        thread_block((void (*)(void))0);
        !           482:                        goto relock;
        !           483:                        break;
        !           484: 
        !           485:                default:
        !           486:                        /*
        !           487:                         * Swapped in or not swappable -- finally!
        !           488:                         */
        !           489:                        unlock_swap_state(thr_act);
        !           490:                        return (TRUE);
        !           491:                }
        !           492:                if (!thr_act->active)
        !           493:                        break;  /* out of loop -- don'tcha love C? */
        !           494:        }
        !           495:        return (FALSE);
        !           496: }
        !           497: 
        !           498: #undef lock_swap_state
        !           499: #undef unlock_swap_state
        !           500: 
        !           501: /*
        !           502:  *     thread_doswapin: [exported]
        !           503:  *
        !           504:  *     Swapin the specified thread, if it should be runnable, then put
        !           505:  *     it on a run queue.  No locks should be held on entry, as it is
        !           506:  *     likely that this routine will sleep (waiting for page faults).
        !           507:  */
        !           508: void thread_doswapin(
        !           509:        thread_act_t    thr_act)
        !           510: {
        !           511:        register vm_offset_t    addr;
        !           512:        register int            s;
        !           513:        kern_return_t           kr;
        !           514:        thread_t                thread;
        !           515:        sched_policy_t          *policy;
        !           516:        sf_return_t             sfr;
        !           517: 
        !           518:        /*
        !           519:         *      Wire down the kernel stack.
        !           520:         */
        !           521: 
        !           522:        if (thread_swap_unwire_stack && (thread = thr_act->thread)) {
        !           523:                assert(KERNEL_STACK_SIZE % page_size == 0);
        !           524:                addr = thread->kernel_stack;
        !           525:                /*
        !           526:                 * This pagein can never fail
        !           527:                 */
        !           528: #if    THREAD_SW_DEBUG
        !           529:                if (thread_swap_debug) {
        !           530:                        printf("thread_doswapin(%x): wiring stack %x\n",
        !           531:                               thr_act, trunc_page(addr));
        !           532:                }
        !           533: #endif /* THREAD_SW_DEBUG */
        !           534: #if    MACH_ASSERT
        !           535:                assert(thr_act->kernel_stack_swapped_in == FALSE);
        !           536:                thr_act->kernel_stack_swapped_in = TRUE;
        !           537: #endif /* MACH_ASSERT */
        !           538:                for (;;) {
        !           539:                        kr = vm_map_wire(kernel_map, trunc_page(addr),
        !           540:                                         round_page(addr + KERNEL_STACK_SIZE),
        !           541:                                         VM_PROT_READ|VM_PROT_WRITE,
        !           542:                                         FALSE);
        !           543:                        if (kr == KERN_SUCCESS) {
        !           544:                                break;
        !           545:                        }
        !           546:                        if (kr != KERN_MEMORY_ERROR) {
        !           547:                                printf("vm_map_wire returned 0x%x\n", kr);
        !           548:                                panic("thread_doswapin");
        !           549:                        }
        !           550:                        thread_block((void (*)(void)) 0);
        !           551:                }
        !           552:                vm_map_simplify(kernel_map, addr);
        !           553:        }
        !           554: 
        !           555: #if    THREAD_SWAP_UNWIRE_USER_STACK
        !           556:        if (thread_swap_unwire_user_stack && thr_act->user_stack) {
        !           557:                vm_offset_t     user_stack;
        !           558:                long            user_stack_size;        /* signed ! */
        !           559:                vm_offset_t     start, end;
        !           560:                
        !           561:                user_stack = thr_act->user_stack;
        !           562:                user_stack_size = (long) thr_act->user_stack_size;
        !           563: #if 0
        !           564:                assert(thr_act->user_stack_size % page_size == 0);
        !           565: #endif
        !           566: #if    THREAD_SW_DEBUG
        !           567:                if (thread_swap_debug) {
        !           568:                        printf("thread_doswapin(%x): wiring user stack %x\n",
        !           569:                               thr_act, trunc_page(user_stack));
        !           570:                }
        !           571: #endif /* THREAD_SW_DEBUG */
        !           572: #if    MACH_ASSERT
        !           573:                assert(thr_act->user_stack_swapped_in == FALSE);
        !           574:                thr_act->user_stack_swapped_in = TRUE;
        !           575: #endif /* MACH_ASSERT */
        !           576:                assert(thr_act->map != VM_MAP_NULL);
        !           577:                if (user_stack_size > 0) {
        !           578:                        /* stack grows up */
        !           579:                        start = trunc_page(user_stack);
        !           580:                        end = round_page(user_stack + user_stack_size - 1);
        !           581:                } else {
        !           582:                        /* stack grows down */
        !           583:                        start = trunc_page(user_stack + user_stack_size + 1);
        !           584:                        end = round_page(user_stack);
        !           585:                }
        !           586:                for (;;) {
        !           587:                        kr = vm_map_wire(thr_act->map, start, end,
        !           588:                                         VM_PROT_READ|VM_PROT_WRITE,
        !           589:                                         TRUE);
        !           590:                        if (kr == KERN_SUCCESS) {
        !           591:                                break;
        !           592:                        }
        !           593:                        if (kr != KERN_MEMORY_ERROR) {
        !           594:                                printf("vm_map_wire(user) returned 0x%x\n", kr);
        !           595:                                panic("thread_doswapin 2");
        !           596:                        }
        !           597:                        thread_block((void (*)(void)) 0);
        !           598:                }
        !           599:                vm_map_simplify(thr_act->map, start);
        !           600:        }
        !           601: #endif /* THREAD_SWAP_UNWIRE_USER_STACK */
        !           602: 
        !           603:        /*
        !           604:         *      Make unswappable and wake up waiting thread(s) if needed.
        !           605:         *      Place on run queue if appropriate.  
        !           606:         *
        !           607:         *      This function only operates on threads that had a state
        !           608:         *      of TH_SW_OUT at one time, in which case, there needs
        !           609:         *      to be a reference on the task's resident thread count.
        !           610:         */
        !           611: 
        !           612:        /*
        !           613:         * Increment the resident thread count for the task.
        !           614:         * This has no direct effect here, but serves as a counter
        !           615:         * for the pmap_collect call in thread_swapout.
        !           616:         */
        !           617:        if (thr_act->task != TASK_NULL) {
        !           618:                mutex_lock(&thr_act->task->act_list_lock);
        !           619:                ++thr_act->task->res_act_count;
        !           620:                mutex_unlock(&thr_act->task->act_list_lock);
        !           621:        }
        !           622: 
        !           623:        thread = act_lock_thread(thr_act);
        !           624:        if (thread != THREAD_NULL) {
        !           625:                s = splsched();
        !           626:                thread_lock(thread);
        !           627:        }
        !           628:        if (thr_act->swap_state & TH_SW_MAKE_UNSWAPPABLE) {
        !           629:                thr_act->swap_state = TH_SW_UNSWAPPABLE;
        !           630:        } else {
        !           631:                thr_act->swap_state = TH_SW_IN;
        !           632:        }
        !           633: 
        !           634:        if (thread != THREAD_NULL) {
        !           635:                if (thread->top_act == thr_act) {
        !           636:                        thread->state &= ~TH_SWAPPED_OUT;
        !           637:                        if (thread->state & TH_RUN) {
        !           638:                                policy = &sched_policy[thread->policy];
        !           639:                                sfr = sched_policy->sp_ops.sp_thread_unblock(
        !           640:                                                                policy, thread);
        !           641:                                assert(sfr == SF_SUCCESS);
        !           642:                        }
        !           643:                }
        !           644:                thread_unlock(thread);
        !           645:                (void) splx(s);
        !           646:        }
        !           647:        thread_wakeup((event_t)&thr_act->swap_state);
        !           648:        act_unlock_thread(thr_act);
        !           649: }
        !           650: 
        !           651: /*
        !           652:  *     thread_swapout: [exported]
        !           653:  *
        !           654:  *     Swap out the specified thread (unwire its kernel stack).
        !           655:  *     The thread must already be marked as 'swapping out'.
        !           656:  *
        !           657:  *     Decrement the resident thread count for the task, and if
        !           658:  *     it goes to zero, call pmap_collect on the task's pmap.
        !           659:  *     
        !           660:  *     The thread has an extra reference (obtained by the caller)
        !           661:  *     to keep it from being deallocated during swapout.
        !           662:  */
        !           663: void thread_swapout(
        !           664:        thread_act_t    thr_act)
        !           665: {
        !           666:        register vm_offset_t    addr;
        !           667:        register boolean_t      make_unswappable;
        !           668:        boolean_t               collect;
        !           669:        int                     s;
        !           670:        kern_return_t           kr;
        !           671:        thread_t                thread;
        !           672: 
        !           673:        /*
        !           674:         *      Thread is marked as swapped before we swap it out; if
        !           675:         *      it is awakened while we are swapping it out, it will
        !           676:         *      be put on the swapin list.
        !           677:         */
        !           678: 
        !           679:        /*
        !           680:         * Notify the pcb module that it must update any
        !           681:         * hardware state associated with this thread.
        !           682:         */
        !           683: #if    0       /* XXX */
        !           684:        pcb_synch(thread);
        !           685: #endif
        !           686: 
        !           687:        /*
        !           688:         *      Unwire the kernel stack.
        !           689:         *      No need to lock the thread to check TH_STACK_HANDOFF and
        !           690:         *      get its kernel_stack address, since the thread is blocked
        !           691:         *      somewhere and can't restart without being swapped back in.
        !           692:         */
        !           693: 
        !           694:        if (thread_swap_unwire_stack && (thread = thr_act->thread)) {
        !           695:                assert(KERNEL_STACK_SIZE % page_size == 0);
        !           696:                addr = thread->kernel_stack;
        !           697: #if    THREAD_SW_DEBUG
        !           698:                if (thread_swap_debug) {
        !           699:                        printf("thread_swapout(%x):unwiring stack %x\n",
        !           700:                               thr_act, trunc_page(addr));
        !           701:                }
        !           702: #endif /* THREAD_SW_DEBUG */
        !           703: #if    MACH_ASSERT
        !           704:                assert(thr_act->kernel_stack_swapped_in == TRUE);
        !           705:                thr_act->kernel_stack_swapped_in = FALSE;
        !           706: #endif /* MACH_ASSERT */
        !           707:                kr = vm_map_unwire(kernel_map, trunc_page(addr),
        !           708:                                   round_page(addr + 
        !           709:                                              KERNEL_STACK_SIZE),
        !           710:                                   FALSE);
        !           711:                if (kr != KERN_SUCCESS) {
        !           712:                        printf("vm_map_unwire returned %x\n", kr);
        !           713:                        panic("thread_swapout");
        !           714:                }
        !           715:                vm_map_simplify(kernel_map, addr);
        !           716:        }
        !           717: 
        !           718: #if    THREAD_SWAP_UNWIRE_USER_STACK
        !           719:        if (thread_swap_unwire_user_stack && thr_act->user_stack) {
        !           720:                vm_offset_t     user_stack;
        !           721:                long            user_stack_size;        /* signed ! */
        !           722:                vm_offset_t     start, end;
        !           723: 
        !           724:                user_stack = thr_act->user_stack;
        !           725:                user_stack_size = thr_act->user_stack_size;
        !           726: #if 0
        !           727:                assert(user_stack_size % page_size == 0);
        !           728: #endif
        !           729: #if    THREAD_SW_DEBUG
        !           730:                if (thread_swap_debug) {
        !           731:                        printf("thread_swapout(%x):unwiring user stack %x\n",
        !           732:                               thr_act, trunc_page(user_stack));
        !           733:                }
        !           734: #endif /* THREAD_SW_DEBUG */
        !           735: #if    MACH_ASSERT
        !           736:                assert(thr_act->user_stack_swapped_in == TRUE);
        !           737:                thr_act->user_stack_swapped_in = FALSE;
        !           738: #endif /* MACH_ASSERT */
        !           739:                assert(thr_act->map != VM_MAP_NULL);
        !           740:                if (user_stack_size > 0) {
        !           741:                        /* stack grows up */
        !           742:                        start = trunc_page(user_stack);
        !           743:                        end = round_page(user_stack + user_stack_size - 1);
        !           744:                } else {
        !           745:                        /* stack grows down */
        !           746:                        start = trunc_page(user_stack + user_stack_size + 1);
        !           747:                        end = round_page(user_stack);
        !           748:                }
        !           749:                kr = vm_map_unwire(thr_act->map, start, end, TRUE);
        !           750:                if (kr != KERN_SUCCESS) {
        !           751:                        printf("vm_map_unwire(user_stack) returned %x\n", kr);
        !           752:                        panic("thread_swapout 2");
        !           753:                }
        !           754:                vm_map_simplify(thr_act->map, start);
        !           755:        }
        !           756: #endif /* THREAD_SWAP_UNWIRE_USER_STACK */
        !           757: 
        !           758:        /*
        !           759:         * Arrange to call pmap_collect if this is the last resident
        !           760:         * thread for its task.  The task and its map aren't going
        !           761:         * anywhere because of the extra reference on this thread.
        !           762:         */
        !           763:        mutex_lock(&thr_act->task->act_list_lock);
        !           764:        collect = (--thr_act->task->res_act_count == 0);
        !           765:        mutex_unlock(&thr_act->task->act_list_lock);
        !           766: 
        !           767:        thread = act_lock_thread(thr_act);
        !           768:        s = splsched();
        !           769:        if (thread)
        !           770:                thread_lock(thread);
        !           771:        switch (thr_act->swap_state & TH_SW_STATE) {
        !           772:            case TH_SW_GOING_OUT:
        !           773:                thr_act->swap_state = TH_SW_OUT;
        !           774:                break;
        !           775: 
        !           776:            case TH_SW_WANT_IN:
        !           777:                /* didn't get it out fast enough */
        !           778:                make_unswappable = thr_act->swap_state & TH_SW_MAKE_UNSWAPPABLE;
        !           779:                thr_act->swap_state = TH_SW_OUT;
        !           780:                thread_swapin(thr_act, make_unswappable);
        !           781:                collect = FALSE;        /* don't pmap_collect */
        !           782:                break;
        !           783: 
        !           784:            default:
        !           785:                panic("thread_swapout");
        !           786:        }
        !           787:        if (thread)
        !           788:                thread_unlock(thread);
        !           789:        splx(s);
        !           790:        act_unlock_thread(thr_act);
        !           791:        if (collect) {
        !           792:                /* task and map can't disappear yet */
        !           793:                assert((thr_act->task != TASK_NULL) &&
        !           794:                        (thr_act->task->map != VM_MAP_NULL));
        !           795:                pmap_collect(vm_map_pmap(thr_act->task->map));
        !           796:        }
        !           797: }
        !           798: 
        !           799: /*
        !           800:  *     swapin_thread: [exported]
        !           801:  *
        !           802:  *     This procedure executes as a kernel thread.  Threads that need to
        !           803:  *     be swapped in are swapped in by this thread.
        !           804:  */
        !           805: void swapin_thread(void)
        !           806: {
        !           807:        thread_swappable(current_act(), FALSE);
        !           808:        stack_privilege(current_thread());
        !           809: 
        !           810:        while (TRUE) {
        !           811:                register thread_act_t   thr_act;
        !           812:                register int            s;
        !           813: 
        !           814:                s = splsched();
        !           815:                swapper_lock();
        !           816: 
        !           817:                while (! queue_empty(&swapin_queue)) {
        !           818:                        queue_remove_first(&swapin_queue, thr_act, thread_act_t,
        !           819:                                           swap_queue);
        !           820:                        swapper_unlock();
        !           821:                        splx(s);
        !           822: 
        !           823:                        thread_doswapin(thr_act);
        !           824: 
        !           825:                        s = splsched();
        !           826:                        swapper_lock();
        !           827:                }
        !           828: 
        !           829:                assert_wait((event_t) &swapin_queue, THREAD_UNINT);
        !           830:                swapper_unlock();
        !           831:                splx(s);
        !           832:                thread_block((void (*)(void)) 0);
        !           833:        }
        !           834: }
        !           835: 
        !           836: boolean_t      thread_swapout_allowed = TRUE;
        !           837: 
        !           838: int    last_swap_tick = 0;
        !           839: 
        !           840: /*
        !           841:  *     swapout_threads: [exported]
        !           842:  *
        !           843:  *     This procedure is called periodically by the pageout daemon.  It
        !           844:  *     determines if it should scan for threads to swap and starts that
        !           845:  *     scan if appropriate.
        !           846:  *     The pageout daemon sets the now flag if all the page queues are
        !           847:  *     empty and it wants to start the swapper right away.
        !           848:  */
        !           849: void swapout_threads(
        !           850:        boolean_t       now)
        !           851: {
        !           852:        if (thread_swapout_allowed &&
        !           853:            (now || (sched_tick > (last_swap_tick + max_swap_rate)))) {
        !           854:                last_swap_tick = sched_tick;
        !           855:                thread_wakeup((event_t) &last_swap_tick); /* poke swapper */
        !           856:                thread_block((void (*)(void)) 0);/* let it run if it wants to */
        !           857:        }
        !           858: }
        !           859: 
        !           860: boolean_t thread_swapout_empty_acts = FALSE;
        !           861: 
        !           862: void swapout_scan(void); /* forward */
        !           863: 
        !           864: /*
        !           865:  *     swapout_scan:
        !           866:  *
        !           867:  *     Scan the list of all threads looking for threads to swap.
        !           868:  */
        !           869: void swapout_scan(void)
        !           870: {
        !           871:        register int            s;
        !           872:        register thread_t       thread, prev_thread;
        !           873:        processor_set_t         pset, prev_pset;
        !           874:        thread_act_t            thr_act, prev_act;
        !           875:        task_t                  task, prev_task;
        !           876: 
        !           877:        zone_gc();
        !           878: 
        !           879:        prev_thread = THREAD_NULL;
        !           880:        prev_act = THR_ACT_NULL;
        !           881:        prev_task = TASK_NULL;
        !           882:        prev_pset = PROCESSOR_SET_NULL;
        !           883:        /*
        !           884:         * Ugh.  If an activation is terminated while being swapped
        !           885:         * out, we can no longer count on consistency of the lists
        !           886:         * we're traversing, so we have to start over.
        !           887:         *
        !           888:         * Note: we deliberately leave the "prev" variables alone if
        !           889:         * we restart -- we will remove a ref to them as needed in
        !           890:         * the normal operation of the loop.
        !           891:         */
        !           892: restart:
        !           893:        mutex_lock(&all_psets_lock);
        !           894:        pset = (processor_set_t) queue_first(&all_psets);
        !           895:        while (!queue_end(&all_psets, (queue_entry_t) pset)) {
        !           896:                pset_lock(pset);
        !           897:                task = (task_t) queue_first(&pset->tasks);
        !           898:                while (!queue_end(&pset->tasks, (queue_entry_t) task)) {
        !           899:                        task_lock(task);
        !           900:                        thr_act = (thread_act_t) queue_first(&task->thr_acts);
        !           901:                        while (!queue_end(&task->thr_acts,
        !           902:                                          (queue_entry_t) thr_act)) {
        !           903:                                boolean_t swap_it;
        !           904:                                thread_act_t act;
        !           905: 
        !           906:                                thread = act_lock_thread(thr_act);
        !           907:                                s = splsched();
        !           908:                                if (thread != THREAD_NULL) {
        !           909:                                        thread_lock(thread);
        !           910:                                        swap_it = TRUE;
        !           911:                                        for (act = thread->top_act; act; act = act->lower)
        !           912:                                                if (act->swap_state == TH_SW_UNSWAPPABLE) {
        !           913:                                                        swap_it = FALSE;
        !           914:                                                        break;
        !           915:                                                }
        !           916:                                        if (!swap_it)
        !           917:                                                ;
        !           918:                                        else if (
        !           919:                                            /* don't swap real-time threads */
        !           920:                                            (thread->policy &
        !           921:                                             POLICYCLASS_FIXEDPRI) != 0 || 
        !           922:                                            (thread->state &
        !           923:                                             (TH_RUN|TH_SWAPPED_OUT)) != 0 ||
        !           924:                                            thr_act->swap_state != TH_SW_IN ||
        !           925:                                            (thread->state & TH_UNINT) != 0 ||
        !           926:                                            (sched_tick-thread->sleep_stamp <=
        !           927:                                             maxslp) ||
        !           928:                                            !thr_act->active) {
        !           929:                                                swap_it = FALSE;
        !           930:                                        }
        !           931:                                } else {
        !           932:                                        if (! thread_swapout_empty_acts) {
        !           933:                                                splx(s);
        !           934:                                                act_unlock_thread(thr_act);
        !           935:                                                thr_act = (thread_act_t)
        !           936:                                                        queue_next(&thr_act->thr_acts);
        !           937:                                                continue;
        !           938:                                        }
        !           939:                                        if (thr_act->swap_state == TH_SW_IN &&
        !           940:                                            thr_act->active &&
        !           941:                                            thr_act->thread_pool_next) {
        !           942:                                                swap_it = TRUE;
        !           943:                                        } else {
        !           944:                                                swap_it = FALSE;
        !           945:                                        }
        !           946:                                }
        !           947:                                if (swap_it) {
        !           948:                                        thr_act->swap_state = TH_SW_GOING_OUT;
        !           949:                                        if (thread != THREAD_NULL) {
        !           950:                                                if (thread->top_act ==
        !           951:                                                        thr_act) {
        !           952:                                                        thread->state |=
        !           953:                                                                TH_SWAPPED_OUT;
        !           954:                                                }
        !           955:                                                thread->ref_count++;
        !           956:                                                thread_unlock(thread);
        !           957:                                        }
        !           958:                                        act_locked_act_reference(thr_act);
        !           959:                                        (void) splx(s);
        !           960:                                        act_unlock_thread(thr_act);
        !           961:                                        task->ref_count++;
        !           962:                                        task_unlock(task);
        !           963:                                        pset->ref_count++;
        !           964:                                        pset_unlock(pset);
        !           965:                                        mutex_unlock(&all_psets_lock);
        !           966: 
        !           967:                                        thread_swapout(thr_act); /* swap it */
        !           968: 
        !           969:                                        if (prev_thread != THREAD_NULL) {
        !           970:                                                thread_deallocate(prev_thread);
        !           971:                                        }
        !           972:                                        if (prev_act != THR_ACT_NULL) {
        !           973:                                                act_deallocate(prev_act);
        !           974:                                        }
        !           975:                                        if (prev_task != TASK_NULL) {
        !           976:                                                task_deallocate(prev_task);
        !           977:                                        }
        !           978:                                        if (prev_pset != PROCESSOR_SET_NULL)
        !           979:                                                pset_deallocate(prev_pset);
        !           980: 
        !           981:                                        prev_thread = thread;
        !           982:                                        prev_act = thr_act;
        !           983:                                        prev_task = task;
        !           984:                                        prev_pset = pset;
        !           985:                                        mutex_lock(&all_psets_lock);
        !           986:                                        pset_lock(pset);
        !           987:                                        task_lock(task);
        !           988:                                        thread = act_lock_thread(thr_act);
        !           989:                                        /*
        !           990:                                         * See if current act was terminated; if so,
        !           991:                                         * can't continue with current traversal --
        !           992:                                         * we don't have a valid "next" pointer, and
        !           993:                                         * there's no certain way to acquire one.
        !           994:                                         *
        !           995:                                         * Also check for task having moved between
        !           996:                                         * psets; don't want to continue current
        !           997:                                         * traversal if it has.  (The traversal would
        !           998:                                         * be valid in this case, just not complete.)
        !           999:                                         */
        !          1000:                                        if (!thr_act->active || task->processor_set != pset) {
        !          1001:                                                act_unlock_thread(thr_act);
        !          1002:                                                task_unlock(task);
        !          1003:                                                pset_unlock(pset);
        !          1004:                                                mutex_unlock(&all_psets_lock);
        !          1005:                                                goto restart;
        !          1006:                                        }
        !          1007:                                
        !          1008:                                        s = splsched();
        !          1009:                                        assert(!prev_thread || thread == prev_thread);
        !          1010:                                } else {
        !          1011:                                        if (thread != THREAD_NULL) 
        !          1012:                                                thread_unlock(thread);
        !          1013:                                }
        !          1014:                                splx(s);
        !          1015:                                act_unlock_thread(thr_act);
        !          1016:                                thr_act = (thread_act_t)
        !          1017:                                        queue_next(&thr_act->thr_acts);
        !          1018:                        }
        !          1019:                        task_unlock(task);
        !          1020:                        task = (task_t) queue_next(&task->pset_tasks);
        !          1021:                }
        !          1022:                pset_unlock(pset);
        !          1023:                pset = (processor_set_t) queue_next(&pset->all_psets);
        !          1024:        }
        !          1025:        mutex_unlock(&all_psets_lock);
        !          1026: 
        !          1027:        if (prev_thread != THREAD_NULL) {
        !          1028:                thread_deallocate(prev_thread);
        !          1029:        }
        !          1030:        if (prev_act != THR_ACT_NULL) {
        !          1031:                act_deallocate(prev_act);
        !          1032:        }
        !          1033:        if (prev_task != TASK_NULL) {
        !          1034:                task_deallocate(prev_task);
        !          1035:        }
        !          1036:        if (prev_pset != PROCESSOR_SET_NULL)
        !          1037:                pset_deallocate(prev_pset);
        !          1038: }
        !          1039: 
        !          1040: /*
        !          1041:  *     swapout_thread: [exported]
        !          1042:  *
        !          1043:  *     Executes as a separate kernel thread.  This thread is periodically
        !          1044:  *     woken up.  When this happens, it initiates the scan for threads
        !          1045:  *     to swap.
        !          1046:  */
        !          1047: void swapout_thread(void)
        !          1048: {
        !          1049:        thread_swappable(current_act(), FALSE);
        !          1050:        stack_privilege(current_thread());
        !          1051: 
        !          1052:        spllo();
        !          1053:        while (TRUE) {
        !          1054:                swapout_scan();
        !          1055: 
        !          1056:                assert_wait((event_t)&last_swap_tick, THREAD_UNINT);
        !          1057:                thread_block((void (*) (void)) 0);
        !          1058:        }
        !          1059: }
        !          1060: 
        !          1061: /*
        !          1062:  *     Mark a thread as swappable or unswappable.  May be called at
        !          1063:  *     any time.  No longer assumes thread is swapped in.  Frees
        !          1064:  *     kernel stack backing store when a kernel thread is made
        !          1065:  *     unswappable.  Panics if a kernel thread is subsequently made
        !          1066:  *     swappable.
        !          1067:  */
        !          1068: void thread_swappable(
        !          1069:        thread_act_t    thr_act,
        !          1070:        boolean_t       is_swappable)
        !          1071: {
        !          1072:        int             s;
        !          1073:        thread_t        thread;
        !          1074: 
        !          1075:        thread = act_lock_thread(thr_act);
        !          1076:        if (thread) {
        !          1077:                s = splsched();
        !          1078:                thread_lock(thread);
        !          1079:        }
        !          1080:        if (is_swappable) {
        !          1081:            if (thr_act->swap_state == TH_SW_UNSWAPPABLE) {
        !          1082:                if (thr_act->task == kernel_task) {
        !          1083:                        panic("thread_swappable");
        !          1084:                }
        !          1085:                thr_act->swap_state = TH_SW_IN;
        !          1086:            }
        !          1087:        }
        !          1088:        else {
        !          1089:            switch(thr_act->swap_state) {
        !          1090:                case TH_SW_UNSWAPPABLE:
        !          1091:                        /*
        !          1092:                         * Thread is already unswappable, won't need to
        !          1093:                         * free backing store.
        !          1094:                         */
        !          1095:                        is_swappable = TRUE;
        !          1096:                    break;
        !          1097: 
        !          1098:                case TH_SW_IN:
        !          1099:                    thr_act->swap_state = TH_SW_UNSWAPPABLE;
        !          1100:                    break;
        !          1101: 
        !          1102:                default:
        !          1103:                    do {
        !          1104:                        thread_swapin(thr_act, TRUE);
        !          1105:                        assert_wait((event_t) &thr_act->swap_state, THREAD_UNINT);
        !          1106:                        if (thread) {
        !          1107:                                thread_unlock(thread);
        !          1108:                                splx(s);
        !          1109:                        }
        !          1110:                        act_unlock_thread(thr_act);
        !          1111:                        thread_block((void (*)(void))0);
        !          1112:                        thread = act_lock_thread(thr_act);
        !          1113:                        if (thread) {
        !          1114:                                s = splsched();
        !          1115:                                thread_lock(thread);
        !          1116:                        }
        !          1117:                    } while (thr_act->swap_state != TH_SW_UNSWAPPABLE);
        !          1118:                    break;
        !          1119:            }
        !          1120:        }
        !          1121:        if (thread) {
        !          1122:                thread_unlock(thread);
        !          1123:                splx(s);
        !          1124:        }
        !          1125:        act_unlock_thread(thr_act);
        !          1126: 
        !          1127:        /* 
        !          1128:         * Deallocate kernel stack backing store for any
        !          1129:         * kernel thread made unswappable.
        !          1130:         */
        !          1131:        if (!is_swappable && thr_act->task == kernel_task) {
        !          1132: #if 0
        !          1133:                stack_backing_free(thr_act->kernel_stack, KERNEL_STACK_SIZE);
        !          1134: #endif
        !          1135:        }
        !          1136: }
        !          1137: 
        !          1138: int thread_swap_disable_swapins = 0;
        !          1139: 
        !          1140: void
        !          1141: thread_swap_disable(
        !          1142:        thread_act_t    thr_act)
        !          1143: {
        !          1144:        spl_t           s;
        !          1145:        thread_t        thread;
        !          1146: 
        !          1147:        /*
        !          1148:         * Note: we have to swapin the thread only to make sure
        !          1149:         * that its stacks are wired when we free them.
        !          1150:         */
        !          1151:        thread = act_lock_thread(thr_act);
        !          1152:        if (thread) {
        !          1153:                s = splsched();
        !          1154:                thread_lock(thread);
        !          1155:        }
        !          1156:        if ((thread_swap_unwire_stack || thread_swap_unwire_user_stack) &&
        !          1157:            (thr_act->swap_state != TH_SW_UNSWAPPABLE)) {
        !          1158:                /*
        !          1159:                 * Make the activation unswappable or it might get swapped
        !          1160:                 * before we complete its termination.
        !          1161:                 */
        !          1162:                if (thr_act->swap_state == TH_SW_IN ||
        !          1163:                    thr_act->swap_state == (TH_SW_IN|TH_SW_TASK_SWAPPING)) {
        !          1164:                        thr_act->swap_state = TH_SW_UNSWAPPABLE;
        !          1165:                        if (thread) {
        !          1166:                                thread_unlock(thread);
        !          1167:                                splx(s);
        !          1168:                        }
        !          1169:                        act_unlock_thread(thr_act);
        !          1170:                } else {
        !          1171:                        thr_act->swap_state |= TH_SW_MAKE_UNSWAPPABLE;
        !          1172:                        if (thread) {
        !          1173:                                thread_unlock(thread);
        !          1174:                                splx(s);
        !          1175:                        }
        !          1176:                        act_unlock_thread(thr_act);
        !          1177:                        thread_swap_disable_swapins++;
        !          1178:                        thread_doswapin(thr_act);
        !          1179:                }
        !          1180: 
        !          1181:                assert(thr_act->swap_state == TH_SW_UNSWAPPABLE);
        !          1182:        } else {
        !          1183:                if (thread) {
        !          1184:                        thread_unlock(thread);
        !          1185:                        splx(s);
        !          1186:                }
        !          1187:                act_unlock_thread(thr_act);
        !          1188:        }
        !          1189: }
        !          1190: 
        !          1191: #endif /* UNUSED CODE */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.