Annotation of kernel/bsd/kern/kern_shutdown.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  *     File:   bsd/kern/kern_shutdown.c
        !            27:  *
        !            28:  *     Copyright (C) 1989, NeXT, Inc.
        !            29:  *
        !            30:  * History:
        !            31:  *     Jan 29, 1992 [email protected]
        !            32:  *             Created by munging machdep/m68k/shutdown.c and
        !            33:  *             machdep/m68k/machdep.c into machine-independence.
        !            34:  *
        !            35:  */
        !            36: 
        !            37: #import <cpus.h>
        !            38: #import <quota.h>
        !            39: #import <mach_nbc.h>
        !            40: 
        !            41: #import <sys/param.h>
        !            42: #import <sys/systm.h>
        !            43: #import <sys/kernel.h>
        !            44: // #import <sys/dnlc.h>
        !            45: #import <sys/vm.h>
        !            46: #import <sys/proc.h>
        !            47: #import <sys/user.h>
        !            48: #import <sys/buf.h>
        !            49: #import <sys/reboot.h>
        !            50: #import <sys/conf.h>
        !            51: #import <sys/vnode.h>
        !            52: #import <sys/file.h>
        !            53: #import <sys/clist.h>
        !            54: #import <sys/callout.h>
        !            55: #import <sys/mbuf.h>
        !            56: #import <sys/msgbuf.h>
        !            57: #import <sys/ioctl.h>
        !            58: #import <sys/signal.h>
        !            59: #import <sys/tty.h>
        !            60: #import <kern/task.h>
        !            61: #import <ufs/ufs/quota.h>
        !            62: #import <ufs/ufs/inode.h>
        !            63: #if    NCPUS > 1
        !            64: #import <kern/processor.h>
        !            65: #import <kern/thread.h>
        !            66: #import <kern/lock.h>
        !            67: #endif /* NCPUS > 1 */
        !            68: #import <kern/xpr.h>
        !            69: #import <vm/vm_kern.h>
        !            70: #import <mach/vm_param.h>
        !            71: #import <vm/vm_page.h>
        !            72: #import <kernserv/ns_timer.h>
        !            73: #import <bsd/sys/filedesc.h>
        !            74: 
        !            75: int    waittime = -1;
        !            76: 
        !            77: boot(paniced, howto, command)
        !            78:        int paniced, howto;
        !            79:        char *command;
        !            80: {
        !            81:        register int i;
        !            82:        int s;
        !            83:        struct proc *p = current_proc();        /* XXX */
        !            84: 
        !            85:        md_prepare_for_shutdown(paniced, howto, command);
        !            86: 
        !            87:        if ((howto&RB_NOSYNC)==0 && waittime < 0) {
        !            88:                register struct buf *bp;
        !            89:                int iter, nbusy;
        !            90: 
        !            91:                waittime = 0;
        !            92:                
        !            93:                (void) spl0();
        !            94: 
        !            95:                printf("syncing disks... ");
        !            96: 
        !            97:                /*
        !            98:                 * Release vnodes held by texts before sync.
        !            99:                 */
        !           100:                 
        !           101:                proc_shutdown();                /* handle live procs (deallocate their
        !           102:                                                                        root and current directories). */
        !           103:                kill_tasks();                   /* get rid of all task memory */
        !           104: 
        !           105: #if MACH_NBC
        !           106:                mapfs_cache_clear();
        !           107:                vm_object_cache_clear();        
        !           108: #endif /* MACH_NBC */
        !           109:                if (panicstr == 0)
        !           110:                        vnode_pager_shutdown();         /* NO MORE PAGING - release vnodes */
        !           111: 
        !           112:                sync(p, (void *)NULL, (int *)NULL);
        !           113: 
        !           114:                /*
        !           115:                 * Unmount filesystems
        !           116:                 */
        !           117:                if (panicstr == 0)
        !           118:                        vfs_unmountall();
        !           119: 
        !           120:                for (iter = 0; iter < 20; iter++) {
        !           121:                        nbusy = 0;
        !           122:                        for (bp = &buf[nbuf]; --bp >= buf; )
        !           123:                                if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
        !           124:                                        nbusy++;
        !           125:                        if (nbusy == 0)
        !           126:                                break;
        !           127:                        printf("%d ", nbusy);
        !           128:                        DELAY(40000 * iter);
        !           129:                }
        !           130:                if (nbusy)
        !           131:                        printf("giving up\n");
        !           132:                else
        !           133:                        printf("done\n");
        !           134:                  
        !           135:                /*
        !           136:                 * If we've been adjusting the clock, the todr
        !           137:                 * will be out of synch; adjust it now.
        !           138:                 */
        !           139: //             resettodr();      
        !           140:        }
        !           141: 
        !           142:        /*
        !           143:         * Can't just use an splnet() here to disable the network
        !           144:         * because that will lock out softints which the disk
        !           145:         * drivers depend on to finish DMAs.
        !           146:         */
        !           147:        if_down_all();
        !           148: 
        !           149:        md_shutdown_devices(paniced, howto, command);
        !           150: 
        !           151: #if    NCPUS > 1
        !           152: #define        LOOPCOUNT       1000
        !           153: #define        WAITCOUNT       1000
        !           154: 
        !           155:        for (i = 0; i < NCPUS; i++) {
        !           156:                processor_t     thisprocessor;
        !           157: 
        !           158:                thisprocessor = cpu_to_processor(i);
        !           159:                if (thisprocessor->state != PROCESSOR_OFF_LINE &&
        !           160:                    thisprocessor != current_processor()) {
        !           161:                        register int j,k;
        !           162: 
        !           163:                        processor_shutdown(thisprocessor);
        !           164: 
        !           165:                        j = 0;
        !           166:                        while ( machine_slot[i].running && j < LOOPCOUNT) {
        !           167:                            for (k=0; k< WAITCOUNT; k++) DELAY(1);
        !           168:                            j++;
        !           169:                        }
        !           170:                        
        !           171:                        if (!machine_slot[i].running)
        !           172:                                printf("Processor %d Halted.\n", i);
        !           173:                        else
        !           174:                                printf("Processor %d won't halt.\n", i);
        !           175:                }
        !           176:        }
        !           177: #endif /* NCPUS > 1 */
        !           178: 
        !           179:        md_do_shutdown(paniced, howto, command);
        !           180: }
        !           181: 
        !           182: kill_tasks()
        !           183: {
        !           184:        processor_set_t pset;
        !           185:        task_t          task;
        !           186:        vm_map_t        map, empty_map;
        !           187: 
        !           188:        empty_map = vm_map_create(pmap_create(0), 0, 0, TRUE);
        !           189: 
        !           190:        /*
        !           191:         * Destroy all but the default processor_set.
        !           192:         */
        !           193:        simple_lock(&all_psets_lock);
        !           194:        pset = (processor_set_t) queue_first(&all_psets);
        !           195:        while (!queue_end(&all_psets, (queue_entry_t) pset)) {
        !           196:                if (pset == &default_pset) {
        !           197:                        pset = (processor_set_t) queue_next(&pset->all_psets);
        !           198:                        continue;
        !           199:                }
        !           200:                simple_unlock(&all_psets_lock);
        !           201:                processor_set_destroy(pset);
        !           202:                simple_lock(&all_psets_lock);
        !           203:                pset = (processor_set_t) queue_first(&all_psets);
        !           204:        }
        !           205:        simple_unlock(&all_psets_lock);
        !           206: 
        !           207:        /*
        !           208:         * Kill all the tasks in the default processor set.
        !           209:         */
        !           210:        pset = &default_pset;
        !           211:        pset_lock(pset);
        !           212:        task = (task_t) queue_first(&pset->tasks);
        !           213:        while (pset->task_count) {
        !           214:                pset_remove_task(pset, task);
        !           215:                map = task->map;
        !           216:                if ((map != kernel_map) && (map != empty_map)) {
        !           217:                        task->map = empty_map;
        !           218:                        vm_map_reference(empty_map);
        !           219:                        pset_unlock(pset);
        !           220:                        vm_map_remove(map, vm_map_min(map), vm_map_max(map));
        !           221:                        pset_lock(pset);
        !           222:                }
        !           223:                task = (task_t) queue_first(&pset->tasks);
        !           224:        }
        !           225:        pset_unlock(pset);
        !           226: }
        !           227: 
        !           228: #if NeXT
        !           229: extern int reaper_queue;
        !           230: #endif
        !           231: /*
        !           232:  * proc_shutdown()
        !           233:  *
        !           234:  *     Shutdown down proc system (release references to current and root
        !           235:  *     dirs for each process).
        !           236:  *
        !           237:  * POSIX modifications:
        !           238:  *
        !           239:  *     For POSIX fcntl() file locking call vno_lockrelease() on 
        !           240:  *     the file to release all of its record locks, if any.
        !           241:  */
        !           242: 
        !           243: proc_shutdown()
        !           244: {
        !           245:        struct proc     *p, *self;
        !           246:        struct vnode    **cdirp, **rdirp, *vp;
        !           247:        int             restart, i;
        !           248: 
        !           249:        /*
        !           250:         *      Kill as many procs as we can.  (Except ourself...)
        !           251:         */
        !           252:        self = current_task()->proc;
        !           253:        
        !           254:        /*
        !           255:         * Suspend /etc/init
        !           256:         */
        !           257:        p = pfind(1);
        !           258:        if (p && p != self)
        !           259:                task_suspend(p->task);          /* stop init */
        !           260: 
        !           261:        /*
        !           262:         * Suspend mach_init
        !           263:         */
        !           264:        p = pfind(2);
        !           265:        if (p && p != self)
        !           266:                task_suspend(p->task);          /* stop mach_init */
        !           267: 
        !           268:        printf("Killing all processes ");
        !           269:        /* SIGTERM and ns_sleep to allow process to clean-up */
        !           270:        for (p = allproc.lh_first; p; p = p->p_list.le_next) {
        !           271:                if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self))
        !           272:                        psignal(p, SIGTERM);
        !           273:        }
        !           274:        ns_sleep(2 * 1000000000);
        !           275:        ns_sleep(2 * 1000000000);
        !           276:        /* SIGKILL in case the TERM wasn't heard */
        !           277:        for (p = allproc.lh_first; p; p = p->p_list.le_next) {
        !           278:                if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self))
        !           279:                        psignal(p, SIGKILL);
        !           280:        }
        !           281:        ns_sleep(1000000000);
        !           282:        /* Brute force 'em, if necessary */
        !           283:        p = allproc.lh_first;
        !           284:        while (p) {
        !           285:                if ((p->p_flag&P_SYSTEM) || (p->p_pptr->p_pid == 0) || (p == self)) {
        !           286:                        p = p->p_list.le_next;
        !           287:                }
        !           288:                else {
        !           289:                        /*
        !           290:                         * NOTE: following code ignores sig_lock and plays
        !           291:                         * with exit_thread correctly.  This is OK unless we
        !           292:                         * are a multiprocessor, in which case I do not
        !           293:                         * understand the sig_lock.  This needs to be fixed.
        !           294:                         * XXX
        !           295:                         */
        !           296:                        if (p->exit_thread) {   /* someone already doing it */
        !           297:                                thread_block(); /* give him a chance */
        !           298:                        }
        !           299:                        else {
        !           300:                                p->exit_thread = current_thread();
        !           301:                                printf(".");
        !           302:                                exit1(p, 1);
        !           303:                        }
        !           304:                        p = allproc.lh_first;
        !           305:                }
        !           306:        }
        !           307:        printf("\n");
        !           308:        /*
        !           309:         *      Forcibly free resources of what's left.
        !           310:         */
        !           311:        p = allproc.lh_first;
        !           312:        while (p) {
        !           313:        /*
        !           314:         * Close open files and release open-file table.
        !           315:         * This may block!
        !           316:         */
        !           317:        fdfree(p);
        !           318:        p = p->p_list.le_next;
        !           319:        }
        !           320:        /* Wait for the reaper thread to run, and clean up what we have done 
        !           321:         * before we proceed with the hardcore shutdown. This reduces the race
        !           322:         * between kill_tasks and the reaper thread.
        !           323:         */
        !           324:        thread_wakeup(&reaper_queue);
        !           325:        ns_sleep(2 * 1000000000);
        !           326:        printf("continuing\n");
        !           327:        
        !           328: }
        !           329: 
        !           330: /*
        !           331:  *     Close all file descriptors, called at shutdown time.
        !           332:  */
        !           333: fd_shutdown()
        !           334: {
        !           335:        register struct file *fp, *nextfp;
        !           336: 
        !           337:        for (fp = filehead.lh_first; fp != 0; fp = nextfp) {
        !           338:                nextfp = fp->f_list.le_next;
        !           339:                while (fp->f_count > 1)
        !           340:                        closef(fp);
        !           341:                closef(fp);
        !           342:        }
        !           343: }

unix.superglobalmegacorp.com

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