|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.