|
|
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: * File: bsd/kern/kern_shutdown.c ! 24: * ! 25: * Copyright (C) 1989, NeXT, Inc. ! 26: * ! 27: * History: ! 28: * Jan 29, 1992 [email protected] ! 29: * Created by munging machdep/m68k/shutdown.c and ! 30: * machdep/m68k/machdep.c into machine-independence. ! 31: * ! 32: */ ! 33: ! 34: #import <mach_nbc.h> ! 35: ! 36: #import <sys/param.h> ! 37: #import <sys/systm.h> ! 38: #import <sys/kernel.h> ! 39: #import <sys/vm.h> ! 40: #import <sys/proc.h> ! 41: #import <sys/user.h> ! 42: #import <sys/buf.h> ! 43: #import <sys/reboot.h> ! 44: #import <sys/conf.h> ! 45: #import <sys/vnode.h> ! 46: #import <sys/file.h> ! 47: #import <sys/clist.h> ! 48: #import <sys/callout.h> ! 49: #import <sys/mbuf.h> ! 50: #import <sys/msgbuf.h> ! 51: #import <sys/ioctl.h> ! 52: #import <sys/signal.h> ! 53: #import <sys/tty.h> ! 54: #import <kern/task.h> ! 55: #import <ufs/ufs/quota.h> ! 56: #import <ufs/ufs/inode.h> ! 57: #if NCPUS > 1 ! 58: #import <kern/processor.h> ! 59: #import <kern/thread.h> ! 60: #import <sys/lock.h> ! 61: #endif /* NCPUS > 1 */ ! 62: #import <vm/vm_kern.h> ! 63: #import <mach/vm_param.h> ! 64: #import <sys/filedesc.h> ! 65: #import <mach/host_reboot.h> ! 66: ! 67: int waittime = -1; ! 68: ! 69: boot(paniced, howto, command) ! 70: int paniced, howto; ! 71: char *command; ! 72: { ! 73: register int i; ! 74: int s; ! 75: struct proc *p = current_proc(); /* XXX */ ! 76: int hostboot_option=0; ! 77: /* md_prepare_for_shutdown(paniced, howto, command); */ ! 78: ! 79: if ((howto&RB_NOSYNC)==0 && waittime < 0) { ! 80: register struct buf *bp; ! 81: int iter, nbusy; ! 82: ! 83: waittime = 0; ! 84: ! 85: (void) spl0(); ! 86: ! 87: printf("syncing disks... "); ! 88: ! 89: /* ! 90: * Release vnodes held by texts before sync. ! 91: */ ! 92: ! 93: proc_shutdown(); /* handle live procs (deallocate their ! 94: root and current directories). */ ! 95: #if 0 /* [ */ ! 96: /* NOT MY PROBLEM XXX */ ! 97: kill_tasks(); /* get rid of all task memory */ ! 98: #endif /* 0 ] */ ! 99: ! 100: #if MACH_NBC ! 101: mapfs_cache_clear(); ! 102: vm_object_cache_clear(); ! 103: #endif /* MACH_NBC */ ! 104: if (panicstr == 0) ! 105: vnode_pager_shutdown(); /* NO MORE PAGING - release vnodes */ ! 106: ! 107: sync(p, (void *)NULL, (int *)NULL); ! 108: ! 109: /* ! 110: * Unmount filesystems ! 111: */ ! 112: if (panicstr == 0) ! 113: vfs_unmountall(); ! 114: ! 115: for (iter = 0; iter < 20; iter++) { ! 116: nbusy = 0; ! 117: for (bp = &buf[nbuf]; --bp >= buf; ) ! 118: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) ! 119: nbusy++; ! 120: if (nbusy == 0) ! 121: break; ! 122: printf("%d ", nbusy); ! 123: IOSleep( 4 * nbusy ); ! 124: } ! 125: if (nbusy) ! 126: printf("giving up\n"); ! 127: else ! 128: printf("done\n"); ! 129: ! 130: /* ! 131: * If we've been adjusting the clock, the todr ! 132: * will be out of synch; adjust it now. ! 133: */ ! 134: } ! 135: ! 136: /* ! 137: * Can't just use an splnet() here to disable the network ! 138: * because that will lock out softints which the disk ! 139: * drivers depend on to finish DMAs. ! 140: */ ! 141: if_down_all(); ! 142: #define BSD_DUMMY_HOST 1 ! 143: if (howto & RB_POWERDOWN) ! 144: hostboot_option = HOST_REBOOT_HALT; ! 145: if (howto & RB_HALT) ! 146: hostboot_option = HOST_REBOOT_HALT; ! 147: if (paniced == RB_PANIC) ! 148: hostboot_option = HOST_REBOOT_HALT; ! 149: ! 150: if (hostboot_option == HOST_REBOOT_HALT) ! 151: IOSleep( 1 * 1000 ); ! 152: ! 153: host_reboot(BSD_DUMMY_HOST, hostboot_option); ! 154: } ! 155: ! 156: #if 0 /* [ */ ! 157: kill_tasks() ! 158: { ! 159: processor_set_t pset; ! 160: task_t task; ! 161: vm_map_t map, empty_map; ! 162: ! 163: empty_map = vm_map_create(pmap_create(0), 0, 0, TRUE); ! 164: ! 165: /* ! 166: * Destroy all but the default processor_set. ! 167: */ ! 168: simple_lock(&all_psets_lock); ! 169: pset = (processor_set_t) queue_first(&all_psets); ! 170: while (!queue_end(&all_psets, (queue_entry_t) pset)) { ! 171: if (pset == &default_pset) { ! 172: pset = (processor_set_t) queue_next(&pset->all_psets); ! 173: continue; ! 174: } ! 175: simple_unlock(&all_psets_lock); ! 176: processor_set_destroy(pset); ! 177: simple_lock(&all_psets_lock); ! 178: pset = (processor_set_t) queue_first(&all_psets); ! 179: } ! 180: simple_unlock(&all_psets_lock); ! 181: ! 182: /* ! 183: * Kill all the tasks in the default processor set. ! 184: */ ! 185: pset = &default_pset; ! 186: pset_lock(pset); ! 187: task = (task_t) queue_first(&pset->tasks); ! 188: while (pset->task_count) { ! 189: pset_remove_task(pset, task); ! 190: map = task->map; ! 191: if ((map != kernel_map) && (map != empty_map)) { ! 192: task->map = empty_map; ! 193: vm_map_reference(empty_map); ! 194: pset_unlock(pset); ! 195: vm_map_remove(map, vm_map_min(map), vm_map_max(map)); ! 196: pset_lock(pset); ! 197: } ! 198: task = (task_t) queue_first(&pset->tasks); ! 199: } ! 200: pset_unlock(pset); ! 201: } ! 202: #endif /* 0 ] */ ! 203: ! 204: #if NeXT ! 205: extern int reaper_queue; ! 206: #endif ! 207: /* ! 208: * proc_shutdown() ! 209: * ! 210: * Shutdown down proc system (release references to current and root ! 211: * dirs for each process). ! 212: * ! 213: * POSIX modifications: ! 214: * ! 215: * For POSIX fcntl() file locking call vno_lockrelease() on ! 216: * the file to release all of its record locks, if any. ! 217: */ ! 218: ! 219: proc_shutdown() ! 220: { ! 221: struct proc *p, *self; ! 222: struct vnode **cdirp, **rdirp, *vp; ! 223: int restart, i, TERM_catch; ! 224: ! 225: /* ! 226: * Kill as many procs as we can. (Except ourself...) ! 227: */ ! 228: self = (struct proc *)(get_bsdtask_info(current_task())); ! 229: ! 230: /* ! 231: * Suspend /etc/init ! 232: */ ! 233: p = pfind(1); ! 234: if (p && p != self) ! 235: task_suspend(p->task); /* stop init */ ! 236: ! 237: /* ! 238: * Suspend mach_init ! 239: */ ! 240: p = pfind(2); ! 241: if (p && p != self) ! 242: task_suspend(p->task); /* stop mach_init */ ! 243: ! 244: printf("Killing all processes "); ! 245: ! 246: /* ! 247: * send SIGTERM to those procs interested in catching one ! 248: */ ! 249: for (p = allproc.lh_first; p; p = p->p_list.le_next) { ! 250: if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) { ! 251: if (p->p_sigcatch & sigmask(SIGTERM)) ! 252: psignal(p, SIGTERM); ! 253: } ! 254: } ! 255: /* ! 256: * now wait for up to 5 seconds to allow those procs catching SIGTERM ! 257: * to digest it ! 258: * as soon as these procs have exited, we'll continue on to the next step ! 259: */ ! 260: for (i = 0; i < 50; i++) { ! 261: /* ! 262: * sleep for a tenth of a second ! 263: * and then check to see if the tasks that were sent a ! 264: * SIGTERM have exited ! 265: */ ! 266: IOSleep(100); ! 267: TERM_catch = 0; ! 268: ! 269: for (p = allproc.lh_first; p; p = p->p_list.le_next) { ! 270: if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) { ! 271: if (p->p_sigcatch & sigmask(SIGTERM)) ! 272: TERM_catch++; ! 273: } ! 274: } ! 275: if (TERM_catch == 0) ! 276: break; ! 277: } ! 278: ! 279: /* ! 280: * send a SIGKILL to all the procs still hanging around ! 281: */ ! 282: for (p = allproc.lh_first; p; p = p->p_list.le_next) { ! 283: if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) ! 284: psignal(p, SIGKILL); ! 285: } ! 286: /* ! 287: * wait for up to 2 seconds to allow these procs to exit normally ! 288: */ ! 289: for (i = 0; i < 20; i++) { ! 290: IOSleep(100); ! 291: ! 292: for (p = allproc.lh_first; p; p = p->p_list.le_next) { ! 293: if (((p->p_flag&P_SYSTEM) == 0) && (p->p_pptr->p_pid != 0) && (p != self)) ! 294: break; ! 295: } ! 296: if (!p) ! 297: break; ! 298: } ! 299: ! 300: /* ! 301: * if we still have procs that haven't exited, then brute force 'em ! 302: */ ! 303: p = allproc.lh_first; ! 304: while (p) { ! 305: if ((p->p_flag&P_SYSTEM) || (p->p_pptr->p_pid == 0) || (p == self)) { ! 306: p = p->p_list.le_next; ! 307: } ! 308: else { ! 309: /* ! 310: * NOTE: following code ignores sig_lock and plays ! 311: * with exit_thread correctly. This is OK unless we ! 312: * are a multiprocessor, in which case I do not ! 313: * understand the sig_lock. This needs to be fixed. ! 314: * XXX ! 315: */ ! 316: if (p->exit_thread) { /* someone already doing it */ ! 317: thread_block(0);/* give him a chance */ ! 318: } ! 319: else { ! 320: p->exit_thread = current_thread(); ! 321: printf("."); ! 322: exit1(p, 1); ! 323: } ! 324: p = allproc.lh_first; ! 325: } ! 326: } ! 327: printf("\n"); ! 328: /* ! 329: * Forcibly free resources of what's left. ! 330: */ ! 331: p = allproc.lh_first; ! 332: while (p) { ! 333: /* ! 334: * Close open files and release open-file table. ! 335: * This may block! ! 336: */ ! 337: #ifdef notyet ! 338: /* panics on reboot due to "zfree: non-allocated memory in collectable zone" message */ ! 339: fdfree(p); ! 340: #endif /* notyet */ ! 341: p = p->p_list.le_next; ! 342: } ! 343: /* Wait for the reaper thread to run, and clean up what we have done ! 344: * before we proceed with the hardcore shutdown. This reduces the race ! 345: * between kill_tasks and the reaper thread. ! 346: */ ! 347: /* thread_wakeup(&reaper_queue); */ ! 348: /* IOSleep( 1 * 1000); */ ! 349: printf("continuing\n"); ! 350: } ! 351: ! 352: /* ! 353: * Close all file descriptors, called at shutdown time. ! 354: */ ! 355: fd_shutdown() ! 356: { ! 357: register struct file *fp, *nextfp; ! 358: ! 359: for (fp = filehead.lh_first; fp != 0; fp = nextfp) { ! 360: nextfp = fp->f_list.le_next; ! 361: while (fp->f_count > 1) ! 362: closef(fp); ! 363: closef(fp); ! 364: } ! 365: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.