|
|
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: * HISTORY ! 27: * ! 28: * Revision 1.1.1.1 1998/09/22 21:05:34 wsanchez ! 29: * Import of Mac OS X kernel (~semeria) ! 30: * ! 31: * Revision 1.2 1998/04/29 17:36:06 mburg ! 32: * MK7.3 merger ! 33: * ! 34: * Revision 1.1.24.1 1998/02/03 09:28:42 gdt ! 35: * Merge up to MK7.3 ! 36: * [1998/02/03 09:13:51 gdt] ! 37: * ! 38: * Revision 1.1.22.1 1997/06/17 02:57:54 devrcs ! 39: * Add node incarnation number to uid definition. ! 40: * [1996/09/03 19:31:17 watkins] ! 41: * ! 42: * Revision 1.1.7.3 1995/10/09 17:15:22 devrcs ! 43: * Added ETAP argument to `mutex_init()' call. ! 44: * [1995/09/13 16:04:48 joe] ! 45: * ! 46: * Revision 1.1.7.2 1995/09/18 19:15:00 devrcs ! 47: * Added ETAP argument to `mutex_init()' call. ! 48: * [1995/09/13 16:04:48 joe] ! 49: * ! 50: * Revision 1.1.7.1 1995/02/23 17:31:49 alanl ! 51: * DIPC: Merge from nmk17b2 to nmk18b8. ! 52: * [95/01/05 alanl] ! 53: * ! 54: * Revision 1.1.4.4 1994/12/06 20:11:26 alanl ! 55: * Include norma_protos.h. ! 56: * [94/12/05 mmp] ! 57: * ! 58: * Revision 1.1.4.3 1994/09/09 23:12:57 alanl ! 59: * Merge up to NMK17.3. Note: chose to preserve most of ! 60: * the mmp task_set_inherited_ports solution, with small ! 61: * modifications from the paire solution. ! 62: * ! 63: * Revision 1.4.15.3 1994/08/31 14:13:44 paire ! 64: * In task_set_inherited_ports routine, the ipc_port_release_send ! 65: * routine must not be called while holding the task simple lock. ! 66: * [94/08/26 paire] ! 67: * [94/09/07 alanl] ! 68: * ! 69: * Revision 1.1.4.2 1994/09/01 12:52:22 alanl ! 70: * Fix task_set_inherited_ports to drop ports after releasing the ! 71: * task lock. (With mmp.) ! 72: * [94/08/29 alanl] ! 73: * ! 74: * Revision 1.1.4.1 1994/08/04 02:25:24 mmp ! 75: * DIPC: Merge up from NMK16. ! 76: * DIPC: replace use of norma_get_special_port with ! 77: * dipc_host_priv_port. Eliminate norma_ipc.h. ! 78: * [1994/04/27 23:52:52 alanl] ! 79: * ! 80: * DIPC: separated out from NORMA_IPC. Include ! 81: * <dipc/dipc_funcs.h> rather than <norma/ipc_node.h>. ! 82: * NORMA_TASK must presuppose DIPC. ! 83: * [1994/04/20 18:31:04 alanl] ! 84: * ! 85: * Revision 1.4.21.4 1994/09/23 02:49:55 ezf ! 86: * change marker to not FREE ! 87: * [1994/09/22 21:46:48 ezf] ! 88: * ! 89: * Revision 1.4.21.3 1994/09/10 21:47:13 bolinger ! 90: * Merge up to NMK17.3 ! 91: * [1994/09/08 19:58:01 bolinger] ! 92: * ! 93: * Revision 1.4.21.2 1994/06/21 19:43:02 dlb ! 94: * Use mutex_init to initialize new task's lock. ! 95: * Add additional argument to task_create_local(). ! 96: * [94/06/16 dlb] ! 97: * ! 98: * Revision 1.4.21.1 1994/06/14 22:39:26 robert ! 99: * merge forward ! 100: * [1994/06/14 22:04:58 robert] ! 101: * ! 102: * Revision 1.4.19.2 1994/06/14 13:29:35 dswartz ! 103: * Preemption merge ! 104: * ! 105: * Revision 1.4.15.3 1994/08/31 14:13:44 paire ! 106: * In task_set_inherited_ports routine, the ipc_port_release_send ! 107: * routine must not be called while holding the task simple lock. ! 108: * [94/08/26 paire] ! 109: * ! 110: * Revision 1.4.15.2 1994/03/11 15:27:17 bernadat ! 111: * Fixed misordered parameters in norma_task_common(). ! 112: * Fixed test against TASK_PORT_REGISTER_MAX in ! 113: * task_set_inherited_ports(). ! 114: * [94/03/11 bernadat] ! 115: * ! 116: * Revision 1.4.15.1 1994/03/07 16:52:36 paire ! 117: * Implemented new exception ports. ! 118: * [94/02/22 paire] ! 119: * ! 120: * Added ANSI prototypes. ! 121: * [94/02/15 paire] ! 122: * ! 123: * Added mcmsg.h (machine dependent, needs to be fixed) ! 124: * Change from NMK16.1 [93/12/03 bernadat] ! 125: * ! 126: * Added init. of new_task->itk_lock_data in norma_task_common(). ! 127: * Fixed a typo from last merge. ! 128: * In task_[sg]et_inherited_ports(), task_[sg]et_special_port() ! 129: * must be called without any lock held. ! 130: * Change from NMK16.1 [93/11/30 paire] ! 131: * ! 132: * Added missing semicolon preventing sequent MP build. ! 133: * Change from NMK16.1 [93/08/18 bernadat] ! 134: * ! 135: * Fixes for ANSI C ! 136: * Change from NMK16.1 [93/07/20 bernadat] ! 137: * ! 138: * [Joseph Barerra:[email protected]] Added norma_task_teleport ! 139: * call for task migration. ! 140: * Change from NORMA_MK14.6 [93/03/08 sjs] ! 141: * [94/02/04 paire] ! 142: * ! 143: * Revision 1.4.2.2 1993/06/09 02:46:16 gm ! 144: * Added to OSF/1 R1.3 from NMK15.0. ! 145: * [1993/06/02 21:21:05 jeffc] ! 146: * ! 147: * Revision 1.4 1993/04/19 16:57:22 devrcs ! 148: * Use task_{set,get}_special_port for norma_task_create ! 149: * instead of referencing itk_exception which does not exist ! 150: * anymore. For the final solution (transfering all exception ! 151: * ports) we need to change the internal MIG stub and probably ! 152: * and need also to split the exception_action structure to pass ! 153: * it through mig. ! 154: * [93/03/02 bernadat] ! 155: * ! 156: * Revision 1.3 1992/12/07 21:30:14 robert ! 157: * integrate any changes below for 14.0 (branch from 13.16 base) ! 158: * ! 159: * Dave Mitchell (dwm) at Open Software Foundation 23-Oct-92 ! 160: * Rearrange task_create() et al. to prevent user code from ! 161: * being able to pass in a null parent. (#478) ! 162: * ! 163: * Joseph Barrera (jsb) at Carnegie-Mellon University 11-Sep-92 ! 164: * This version now supports VM_INHERIT_SHARE. ! 165: * Added norma_task_clone to support task migration. ! 166: * Use norma_get_special_port() instead of remote_host(). ! 167: * Moved task_copy_vm to norma/vm_copy.c. Removed babble routine. ! 168: * Placed task_create_remote_node feature under TASK_CREATE_USE_REMOTE ! 169: * conditional. Folded task initialization calls into norma_task_allocate. ! 170: * Removed norma_task_server and associated lock. Check for null parent ! 171: * task in task_create. Terminate task upon address space copy failure. ! 172: * [1992/12/06 20:51:48 robert] ! 173: * ! 174: * Revision 1.2 1992/11/25 01:15:11 robert ! 175: * fix history ! 176: * [1992/11/09 21:58:59 robert] ! 177: * ! 178: * integrate changes below for norma_14 ! 179: * [1992/11/09 16:47:47 robert] ! 180: * ! 181: * Revision 1.1 1992/11/05 21:00:06 robert ! 182: * Initial revision ! 183: * [92/10/23 dwm] ! 184: * ! 185: * Revision 0.0 92/10/23 dwm ! 186: * Terminate remote_task in norma_task_create() error path, ! 187: * to avoid leaving remote orphans hanging around, and avoid ! 188: * returning random MiG errors. (#471, 475). ! 189: * Rearrange task_create() et al. to prevent user code from ! 190: * being able to pass in a null parent. (#478) ! 191: * ! 192: * $EndLog$ ! 193: */ ! 194: /* CMU_HIST */ ! 195: /* ! 196: * Revision 2.7.2.7 92/09/15 17:34:52 jeffreyh ! 197: * When inheriting memory in task_copy_vm, set protection in ! 198: * locally forked map to max. This deals with regions that are ! 199: * currently unreadable but could become readable in the future. ! 200: * Don't set up cross node copy logic for permanently unreadable ! 201: * regions. Don't copy read-only regions. ! 202: * [92/08/14 dlb] ! 203: * ! 204: * Add bounds checking on the node to task_set_child_node ! 205: * and norma_task_create. ! 206: * [92/07/23 jeffreyh] ! 207: * ! 208: * Revision 2.7.2.6 92/05/28 18:20:32 jeffreyh ! 209: * Add new type argument to remote_host call ! 210: * ! 211: * Revision 2.7.2.5 92/05/27 00:53:43 jeffreyh ! 212: * norma_task_create inits mcmsg_task in MCMSG ifdef ! 213: * [[email protected]] ! 214: * ! 215: * Revision 2.7.2.4 92/03/04 16:07:16 jeffreyh ! 216: * Converted to use out-of-line forms of task_{get,set}_emulation_vector. ! 217: * [92/03/04 14:55:51 jsb] ! 218: * ! 219: * Revision 2.7.2.3 92/02/21 11:25:15 jsb ! 220: * Release send right to memory_object after mapping it in remote task ! 221: * in task_copy_vm. ! 222: * [92/02/20 10:29:45 jsb] ! 223: * ! 224: * Set copy flag TRUE in r_vm_map call in task_copy_vm. ! 225: * This is now practical due to smarter copy strategy management ! 226: * in xmm_svm (compared to when it always used MEMORY_OBJECT_COPY_NONE). ! 227: * It also keeps xmm_copy from having to deal with data writes without ! 228: * having to use an xmm_shadow layer. ! 229: * [92/02/11 11:39:23 jsb] ! 230: * ! 231: * Release map reference in task_copy_vm. ! 232: * [92/01/22 10:29:57 jsb] ! 233: * ! 234: * Revision 2.7.2.2 92/01/09 18:46:08 jsb ! 235: * Added logic in task_create to alternate task creation between local ! 236: * node and a patchable remote node. For testing purposes only. ! 237: * [92/01/08 16:41:27 jsb] ! 238: * ! 239: * Use varargs for debugging printfs. ! 240: * [92/01/08 10:22:12 jsb] ! 241: * ! 242: * Use remote_host() instead of norma_get_special_port(). ! 243: * [92/01/04 18:17:46 jsb] ! 244: * ! 245: * Revision 2.7.2.1 92/01/03 16:38:29 jsb ! 246: * Removed unused routine ipc_task_reinit. ! 247: * [91/12/28 17:59:18 jsb] ! 248: * ! 249: * Revision 2.7 91/12/13 13:53:22 jsb ! 250: * Changed name of task_create_remote to norma_task_create. ! 251: * Added check for local case in norma_task_create. ! 252: * ! 253: * Revision 2.6 91/12/10 13:26:19 jsb ! 254: * Changed printfs to frets. ! 255: * [91/12/10 11:34:35 jsb] ! 256: * ! 257: * Revision 2.5 91/11/14 16:51:51 rpd ! 258: * Use new child_node task field in place of task_server_node to decide ! 259: * upon what node to create child task. Also add task_set_child_node(). ! 260: * [91/09/23 09:22:18 jsb] ! 261: * ! 262: * Revision 2.4 91/08/28 11:16:18 jsb ! 263: * Turned off remaining printf. ! 264: * [91/08/26 11:16:11 jsb] ! 265: * ! 266: * Added support for remote task creation with inherited memory. ! 267: * Remove task creation is accessible either via task_create_remote, ! 268: * or task_create with task_server_node patched to some reasonable value. ! 269: * [91/08/15 13:55:54 jsb] ! 270: * ! 271: * Revision 2.3 91/06/17 15:48:07 jsb ! 272: * Moved routines here from kern/ipc_tt.c and kern/task.c. ! 273: * [91/06/17 11:01:51 jsb] ! 274: * ! 275: * Revision 2.2 91/06/06 17:08:15 jsb ! 276: * First checkin. ! 277: * [91/05/25 11:47:39 jsb] ! 278: * ! 279: */ ! 280: /* CMU_ENDHIST */ ! 281: /* ! 282: * Mach Operating System ! 283: * Copyright (c) 1991 Carnegie Mellon University ! 284: * All Rights Reserved. ! 285: * ! 286: * Permission to use, copy, modify and distribute this software and its ! 287: * documentation is hereby granted, provided that both the copyright ! 288: * notice and this permission notice appear in all copies of the ! 289: * software, derivative works or modified versions, and any portions ! 290: * thereof, and that both notices appear in supporting documentation. ! 291: * ! 292: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 293: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 294: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 295: * ! 296: * Carnegie Mellon requests users of this software to return to ! 297: * ! 298: * Software Distribution Coordinator or [email protected] ! 299: * School of Computer Science ! 300: * Carnegie Mellon University ! 301: * Pittsburgh PA 15213-3890 ! 302: * ! 303: * any improvements or extensions that they make and grant Carnegie Mellon ! 304: * the rights to redistribute these changes. ! 305: */ ! 306: /* ! 307: */ ! 308: /* ! 309: * File: norma/kern_task.c ! 310: * Author: Joseph S. Barrera III ! 311: * ! 312: * NORMA task support. ! 313: */ ! 314: ! 315: #include <dipc.h> ! 316: #include <norma_vm.h> ! 317: #include <norma_task.h> ! 318: ! 319: #include <mach/machine/vm_types.h> ! 320: #include <mach/vm_param.h> ! 321: #include <mach/mach_norma_server.h> ! 322: #include <mach/task_server.h> ! 323: #include <mach/thread_act_server.h> ! 324: #include <mach/vm_task_server.h> ! 325: #include <kern/norma_task_server.h> ! 326: #include <xmm/xmm_internal.h> ! 327: #include <mach/task_info.h> ! 328: #include <mach/task_special_ports.h> ! 329: #include <mach/norma_special_ports.h> ! 330: #include <ipc/ipc_space.h> ! 331: #include <kern/mach_param.h> ! 332: #include <kern/task.h> ! 333: #include <kern/host.h> ! 334: #include <kern/thread.h> ! 335: #include <kern/zalloc.h> ! 336: #include <kern/kalloc.h> ! 337: #include <kern/processor.h> ! 338: #include <kern/ipc_tt.h> ! 339: #include <kern/misc_protos.h> ! 340: #include <kern/norma_protos.h> ! 341: #include <kern/norma_task.h> /* mig-generated */ ! 342: #if DIPC ! 343: #include <dipc/dipc_funcs.h> ! 344: #include <dipc/special_ports.h> ! 345: #endif ! 346: ! 347: ! 348: /* ! 349: * XXX This definition should be elsewhere ! 350: */ ! 351: kern_return_t ! 352: norma_node_self( ! 353: host_t host, ! 354: int *node) ! 355: { ! 356: #if DIPC ! 357: *node = dipc_node_self(); ! 358: return KERN_SUCCESS; ! 359: #else ! 360: panic("norma_node_self: no transport"); ! 361: return KERN_INVALID_ARGUMENT; ! 362: #endif ! 363: } ! 364: ! 365: #if NORMA_TASK ! 366: ! 367: /* ! 368: * Forward. ! 369: */ ! 370: kern_return_t task_get_inherited_ports( ! 371: task_t task, ! 372: ipc_port_t *bootstrap, ! 373: norma_registered_port_array_t registered, ! 374: unsigned *count, ! 375: exception_mask_array_t exc_masks, ! 376: unsigned *exc_count, ! 377: exception_port_array_t exc_ports, ! 378: exception_behavior_array_t exc_behaviors, ! 379: exception_flavor_array_t exc_flavors); ! 380: ! 381: kern_return_t task_set_inherited_ports( ! 382: task_t task, ! 383: ipc_port_t bootstrap, ! 384: norma_registered_port_array_t registered, ! 385: unsigned count, ! 386: exception_mask_array_t exc_masks, ! 387: unsigned exc_count, ! 388: exception_port_array_t exc_ports, ! 389: exception_behavior_array_t exc_behaviors, ! 390: exception_flavor_array_t exc_flavors); ! 391: ! 392: kern_return_t norma_task_common( ! 393: task_t parent_task, ! 394: boolean_t inherit_memory, ! 395: boolean_t clone, ! 396: boolean_t kill_parent, ! 397: int child_node, ! 398: task_t *child_task); ! 399: ! 400: extern zone_t task_zone; ! 401: ! 402: /* ! 403: * This is a debugging/testing hack to allow a system with an unmodified ! 404: * server to run tasks automatically alternately on local node and some ! 405: * remote node specified by a patchable variable (task_create_remote_node). ! 406: */ ! 407: #define TASK_CREATE_USE_REMOTE 1 ! 408: #if TASK_CREATE_USE_REMOTE ! 409: int task_create_remote_node = -1; ! 410: boolean_t task_create_use_remote = FALSE; ! 411: #endif /* TASK_CREATE_USE_REMOTE */ ! 412: ! 413: kern_return_t ! 414: task_create( ! 415: task_t parent_task, ! 416: ledger_port_array_t ledger_ports, ! 417: mach_msg_type_number_t ledger_portsCnt, ! 418: boolean_t inherit_memory, ! 419: task_t *child_task) /* OUT */ ! 420: { ! 421: #if TASK_CREATE_USE_REMOTE ! 422: if (task_create_remote_node != -1) { ! 423: task_create_use_remote = ! task_create_use_remote; ! 424: if (task_create_use_remote) { ! 425: return norma_task_create(parent_task, inherit_memory, ! 426: task_create_remote_node, ! 427: child_task); ! 428: } else { ! 429: return task_create_local(parent_task, inherit_memory, ! 430: FALSE, child_task); ! 431: } ! 432: } ! 433: #endif /* TASK_CREATE_USE_REMOTE */ ! 434: if (! parent_task || parent_task->child_node == -1) { ! 435: return task_create_local(parent_task, inherit_memory, ! 436: FALSE, child_task); ! 437: } else { ! 438: return norma_task_create(parent_task, inherit_memory, ! 439: (int) parent_task->child_node, ! 440: child_task); ! 441: } ! 442: } ! 443: ! 444: kern_return_t ! 445: task_set_child_node( ! 446: task_t task, ! 447: int child_node) ! 448: { ! 449: #if DIPC ! 450: if (task == TASK_NULL || !dipc_node_is_valid (child_node)) { ! 451: return KERN_INVALID_ARGUMENT; ! 452: } else { ! 453: task->child_node = child_node; ! 454: return KERN_SUCCESS; ! 455: } ! 456: #else /* DIPC */ ! 457: printf("task_set_child_node: no underlying transport!\n"); ! 458: return KERN_INVALID_ARGUMENT; ! 459: #endif /* DIPC */ ! 460: } ! 461: ! 462: /* ! 463: * This allows us to create a task without providing a parent. ! 464: * ! 465: * XXX ! 466: * Should deallocate resouces upon failure ! 467: */ ! 468: kern_return_t ! 469: norma_task_allocate( ! 470: host_t host, ! 471: int vector_start, ! 472: emulation_vector_t entry_vector, ! 473: unsigned int entry_vector_count, ! 474: ipc_port_t bootstrap, ! 475: norma_registered_port_array_t registered, ! 476: unsigned count, ! 477: exception_mask_array_t exc_masks, ! 478: unsigned exc_count, ! 479: exception_port_array_t exc_ports, ! 480: exception_behavior_array_t exc_behaviors, ! 481: exception_flavor_array_t exc_flavors, ! 482: task_t *result) /* OUT */ ! 483: { ! 484: kern_return_t kr; ! 485: task_t task; ! 486: ! 487: if (host == HOST_NULL) { ! 488: return KERN_INVALID_ARGUMENT; ! 489: } ! 490: kr = task_create_local(TASK_NULL, FALSE, FALSE, &task); ! 491: if (kr != KERN_SUCCESS) { ! 492: return kr; ! 493: } ! 494: kr = task_set_emulation_vector(task, vector_start, entry_vector, ! 495: entry_vector_count); ! 496: if (kr != KERN_SUCCESS) { ! 497: return kr; ! 498: } ! 499: kr = task_set_inherited_ports(task, bootstrap, registered, count, ! 500: exc_masks, exc_count, exc_ports, ! 501: exc_behaviors, exc_flavors); ! 502: if (kr != KERN_SUCCESS) { ! 503: printf("task_set_inherited_ports failed: kr %d %x\n", kr, kr); ! 504: return kr; ! 505: } ! 506: *result = task; ! 507: return KERN_SUCCESS; ! 508: } ! 509: ! 510: kern_return_t ! 511: task_get_inherited_ports( ! 512: task_t task, ! 513: ipc_port_t *bootstrap, ! 514: norma_registered_port_array_t registered, ! 515: unsigned *count, ! 516: exception_mask_array_t exc_masks, ! 517: unsigned *exc_count, ! 518: exception_port_array_t exc_ports, ! 519: exception_behavior_array_t exc_behaviors, ! 520: exception_flavor_array_t exc_flavors) ! 521: { ! 522: unsigned i; ! 523: unsigned j; ! 524: unsigned n; ! 525: ! 526: if (task == TASK_NULL) { ! 527: return KERN_INVALID_ARGUMENT; ! 528: } ! 529: ! 530: itk_lock(task); ! 531: *bootstrap = ipc_port_copy_send(task->itk_bootstrap); ! 532: ! 533: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) ! 534: registered[i] = ipc_port_copy_send(task->itk_registered[i]); ! 535: *count = TASK_PORT_REGISTER_MAX; ! 536: ! 537: n = 0; ! 538: for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) { ! 539: for (j = 0; j < n; j++) { ! 540: /* ! 541: * Search for an identical entry, if found ! 542: * set corresponding mask for this exception. ! 543: */ ! 544: if (task->exc_actions[i].port == exc_ports[j] && ! 545: task->exc_actions[i].behavior == exc_behaviors[j] && ! 546: task->exc_actions[i].flavor == exc_flavors[j]) { ! 547: exc_masks[j] |= (1 << i); ! 548: break; ! 549: } ! 550: } ! 551: if (j == n) { ! 552: exc_masks[j] = (1 << i); ! 553: exc_ports[j] = ! 554: ipc_port_copy_send(task->exc_actions[i].port); ! 555: exc_behaviors[j] = task->exc_actions[i].behavior; ! 556: exc_flavors[j] = task->exc_actions[i].flavor; ! 557: n++; ! 558: } ! 559: } ! 560: *exc_count = n; ! 561: itk_unlock(task); ! 562: ! 563: return KERN_SUCCESS; ! 564: } ! 565: ! 566: ! 567: /* ! 568: * It's not a good idea to be releasing send rights to ports ! 569: * while holding the task lock -- the send rights could get ! 570: * deallocated or could result in message traffic (at least ! 571: * in the DIPC case). So save pointers to all the ports we ! 572: * would deallocate, and drop them at the end. ! 573: * ! 574: * Possible ports to deallocate: ! 575: * itk_bootstrap (per-task) ! 576: * itk_registered[TASK_PORT_REGISTER_MAX] (per-task) ! 577: * exc_actions[EXC_TYPES_COUNT] (per-task) ! 578: * exc_ports[EXC_TYPES_COUNT] (passed in by caller) ! 579: */ ! 580: #define TSIP_DROP_MAX (1 + TASK_PORT_REGISTER_MAX + (EXC_TYPES_COUNT * 2)) ! 581: ! 582: kern_return_t ! 583: task_set_inherited_ports( ! 584: task_t task, ! 585: ipc_port_t bootstrap, ! 586: norma_registered_port_array_t registered, ! 587: unsigned count, ! 588: exception_mask_array_t exc_masks, ! 589: unsigned exc_count, ! 590: exception_port_array_t exc_ports, ! 591: exception_behavior_array_t exc_behaviors, ! 592: exception_flavor_array_t exc_flavors) ! 593: { ! 594: exception_mask_t mask; ! 595: ipc_port_t drop_ports[TSIP_DROP_MAX]; ! 596: unsigned int drop_port_count = 0; ! 597: unsigned i; ! 598: unsigned j; ! 599: ! 600: if (task == TASK_NULL) ! 601: return KERN_INVALID_ARGUMENT; ! 602: ! 603: if (count > TASK_PORT_REGISTER_MAX+1) ! 604: return KERN_INVALID_ARGUMENT; ! 605: ! 606: mask = 0; ! 607: for (i = 0; i < exc_count; i++) { ! 608: if ((exc_masks[i] & ~EXC_MASK_ALL) || (mask & exc_masks[i])) ! 609: return KERN_INVALID_ARGUMENT; ! 610: mask |= exc_masks[i]; ! 611: } ! 612: ! 613: if (exc_count >= EXC_TYPES_COUNT) ! 614: return KERN_INVALID_ARGUMENT; ! 615: ! 616: itk_lock(task); ! 617: /* ! 618: * First, set up bootstrap port. ! 619: */ ! 620: if (IP_VALID(task->itk_bootstrap)) { ! 621: assert(drop_port_count < TSIP_DROP_MAX); ! 622: drop_ports[drop_port_count++] = task->itk_bootstrap; ! 623: } ! 624: task->itk_bootstrap = bootstrap; ! 625: ! 626: /* ! 627: * Next, set up registered ports. ! 628: */ ! 629: for (i = 0; i < count; i++) { ! 630: if (IP_VALID(task->itk_registered[i])) { ! 631: assert(drop_port_count < TSIP_DROP_MAX); ! 632: drop_ports[drop_port_count++] = task->itk_registered[i]; ! 633: } ! 634: task->itk_registered[i] = registered[i]; ! 635: } ! 636: ! 637: /* ! 638: * Finally, set up exception ports. ! 639: */ ! 640: for (i = 0; i < exc_count; i++) { ! 641: mask = exc_masks[i] & ~EXC_MASK_ALL; ! 642: j = 0; ! 643: while (mask) { ! 644: if (mask & 1) { ! 645: if (IP_VALID(task->exc_actions[j].port)) { ! 646: assert(drop_port_count < TSIP_DROP_MAX); ! 647: drop_ports[drop_port_count++] = ! 648: task->exc_actions[j].port; ! 649: } ! 650: task->exc_actions[j].port = ! 651: ipc_port_copy_send(exc_ports[i]); ! 652: task->exc_actions[j].behavior = ! 653: exc_behaviors[i]; ! 654: task->exc_actions[j].flavor = exc_flavors[i]; ! 655: } ! 656: mask >>= 1; ! 657: j++; ! 658: } ! 659: if (IP_VALID(exc_ports[i])) { /* consume send right */ ! 660: assert(drop_port_count < TSIP_DROP_MAX); ! 661: drop_ports[drop_port_count++] = exc_ports[i]; ! 662: } ! 663: } ! 664: itk_unlock(task); ! 665: ! 666: for (i = 0; i < drop_port_count; ++i) ! 667: ipc_port_release_send(drop_ports[i]); ! 668: ! 669: return KERN_SUCCESS; ! 670: } ! 671: ! 672: kern_return_t ! 673: norma_task_common( ! 674: task_t parent_task, ! 675: boolean_t inherit_memory, ! 676: boolean_t clone, ! 677: boolean_t kill_parent, ! 678: int child_node, ! 679: task_t *child_task) ! 680: { ! 681: ipc_port_t remote_task, remote_host; ! 682: task_t new_task; ! 683: kern_return_t kr; ! 684: int vector_start; ! 685: unsigned int entry_vector_count; ! 686: ipc_port_t bootstrap; ! 687: emulation_vector_t entry_vector; ! 688: ipc_port_t registered[TASK_PORT_REGISTER_MAX]; ! 689: exception_mask_t exc_masks[EXC_TYPES_COUNT]; ! 690: ipc_port_t exc_ports[EXC_TYPES_COUNT]; ! 691: exception_behavior_t exc_behaviors[EXC_TYPES_COUNT]; ! 692: thread_state_flavor_t exc_flavors[EXC_TYPES_COUNT]; ! 693: unsigned count, exc_count; ! 694: ! 695: #if DIPC ! 696: if (!dipc_node_is_valid (child_node)) { ! 697: return KERN_INVALID_ARGUMENT; ! 698: } ! 699: ! 700: if (child_node == dipc_node_self()) { ! 701: if (clone) { ! 702: /* ! 703: * Cloning: easy if kill_parent; ! 704: * (currently) impossible otherwise. ! 705: */ ! 706: if (kill_parent) { ! 707: /* ! 708: * Just return the parent -- nothing says that ! 709: * the clone has to be a different task. ! 710: */ ! 711: *child_task = parent_task; ! 712: return KERN_SUCCESS; ! 713: } else { ! 714: /* ! 715: * XXX ! 716: * There is no local call we can use with the ! 717: * same memory semantics -- we'd have to ! 718: * modify task_create_local, and vm_map_fork. ! 719: * Not hard, just probably unnecessary except ! 720: * for orthogonality. ! 721: */ ! 722: return KERN_INVALID_ARGUMENT; ! 723: } ! 724: } else { ! 725: /* ! 726: * Not cloning: just use task_create_local, ! 727: * and task_terminate if appropriate. ! 728: */ ! 729: kr = task_create_local(parent_task, inherit_memory, ! 730: FALSE, child_task); ! 731: if (kr != KERN_SUCCESS) { ! 732: return kr; ! 733: } ! 734: if (kill_parent) { ! 735: kr = task_terminate(parent_task); ! 736: if (kr != KERN_SUCCESS) { ! 737: /* cleanup */ ! 738: (void) task_terminate(*child_task); ! 739: return kr; ! 740: } ! 741: } ! 742: return KERN_SUCCESS; ! 743: } ! 744: } ! 745: ! 746: kr = task_get_emulation_vector(parent_task, &vector_start, ! 747: &entry_vector, &entry_vector_count); ! 748: if (kr != KERN_SUCCESS) { ! 749: printf("task_get_emulation_vector failed: kr %d %x\n", kr, kr); ! 750: return kr; ! 751: } ! 752: ! 753: kr = task_get_inherited_ports(parent_task, &bootstrap, registered, ! 754: &count, exc_masks, &exc_count, ! 755: exc_ports, exc_behaviors, exc_flavors); ! 756: if (kr != KERN_SUCCESS) { ! 757: printf("task_get_inherited_ports failed: kr %d %x\n", kr, kr); ! 758: return kr; ! 759: } ! 760: ! 761: remote_host = dipc_host_priv_port(child_node); ! 762: if (remote_host == IP_NULL) { ! 763: panic("norma_task_create: no priv port for node %d\n", ! 764: child_node); ! 765: return KERN_INVALID_ARGUMENT; ! 766: } ! 767: ! 768: kr = r_norma_task_allocate(remote_host, vector_start, entry_vector, ! 769: entry_vector_count, bootstrap, ! 770: registered, count, exc_masks, exc_count, ! 771: exc_ports, exc_behaviors, exc_flavors, ! 772: &remote_task); ! 773: if (kr != KERN_SUCCESS) { ! 774: return kr; ! 775: } ! 776: ! 777: if (inherit_memory) { ! 778: task_copy_vm(remote_host, parent_task->map, clone, ! 779: kill_parent, remote_task); ! 780: } ! 781: ! 782: if (kill_parent) { ! 783: (void) task_terminate(parent_task); ! 784: } ! 785: ! 786: /* ! 787: * Create a placeholder task for the benefit of convert_task_to_port. ! 788: * Set new_task->map to VM_MAP_NULL so that task_deallocate will ! 789: * know that this is only a placeholder task. ! 790: */ ! 791: new_task = (task_t) zalloc(task_zone); ! 792: if (new_task == TASK_NULL) { ! 793: panic("task_create: no memory for task structure"); ! 794: } ! 795: ! 796: #if MCMSG ! 797: new_task->mcmsg_task = 0; ! 798: #endif /* MCMSG */ ! 799: ! 800: /* only one ref, for our caller */ ! 801: new_task->ref_count = 1; ! 802: ! 803: new_task->map = VM_MAP_NULL; ! 804: new_task->itk_self = remote_task; ! 805: mutex_init(&new_task->lock, ETAP_NORMA_TASK); ! 806: itk_lock_init(new_task); ! 807: ! 808: *child_task = new_task; ! 809: return(KERN_SUCCESS); ! 810: #else /* DIPC */ ! 811: printf("norma_task_common: no underlying transport!\n"); ! 812: return KERN_INVALID_ARGUMENT; ! 813: #endif /* DIPC */ ! 814: } ! 815: ! 816: ! 817: #if !NORMA_VM ! 818: /* ! 819: * task_vm_copy ! 820: * ! 821: * Provide a stub for task_copy_vm when we have norma_task but not ! 822: * norma_vm. This allows us to build and link kernels which support ! 823: * dipc and norma_node_self without turning on norma_vm. ! 824: * ! 825: * XXX We need to rearrange things so we can have a dipc subset and ! 826: * basic node information system calls without turning EITHER ! 827: * norma_task or norma_vm on. This is needed for RFT ports. ! 828: */ ! 829: void ! 830: task_copy_vm( ! 831: ipc_port_t host, ! 832: vm_map_t old_map, ! 833: boolean_t clone, ! 834: boolean_t kill_parent, ! 835: ipc_port_t to) ! 836: { ! 837: ! 838: panic("task_copy_vm: norma_vm option not turned on"); ! 839: ! 840: } ! 841: #endif /* !NORMA_VM */ ! 842: ! 843: kern_return_t ! 844: norma_task_create( ! 845: task_t parent_task, ! 846: boolean_t inherit_memory, ! 847: int child_node, ! 848: task_t *child_task) /* OUT */ ! 849: { ! 850: return norma_task_common(parent_task, inherit_memory, FALSE, ! 851: FALSE, child_node, child_task); ! 852: } ! 853: ! 854: kern_return_t ! 855: norma_task_clone( ! 856: task_t parent_task, ! 857: boolean_t inherit_memory, ! 858: int child_node, ! 859: task_t *child_task) /* OUT */ ! 860: { ! 861: return norma_task_common(parent_task, inherit_memory, TRUE, ! 862: FALSE, child_node, child_task); ! 863: } ! 864: ! 865: kern_return_t ! 866: norma_task_teleport( ! 867: task_t parent_task, ! 868: boolean_t inherit_memory, ! 869: int child_node, ! 870: task_t *child_task) /* OUT */ ! 871: { ! 872: return norma_task_common(parent_task, inherit_memory, TRUE, ! 873: TRUE, child_node, child_task); ! 874: } ! 875: ! 876: #else /* NORMA_TASK */ ! 877: ! 878: /*ARGSUSED*/ ! 879: kern_return_t ! 880: norma_task_allocate( ! 881: host_t host, ! 882: int vector_start, ! 883: emulation_vector_t entry_vector, ! 884: unsigned int entry_vector_count, ! 885: ipc_port_t bootstrap, ! 886: norma_registered_port_array_t registered, ! 887: exception_mask_array_t exc_masks, ! 888: unsigned count, ! 889: exception_port_array_t exc_ports, ! 890: exception_behavior_array_t exc_behaviors, ! 891: exception_flavor_array_t exc_flavors ! 892: task_t *result) ! 893: { ! 894: return KERN_FAILURE; ! 895: } ! 896: ! 897: /*ARGSUSED*/ ! 898: kern_return_t ! 899: norma_task_create( ! 900: task_t parent_task, ! 901: boolean_t inherit_memory, ! 902: int child_node, ! 903: task_t *child_task) /* OUT */ ! 904: { ! 905: return KERN_FAILURE; ! 906: } ! 907: ! 908: /*ARGSUSED*/ ! 909: kern_return_t ! 910: norma_task_clone( ! 911: task_t parent_task, ! 912: boolean_t inherit_memory, ! 913: int child_node, ! 914: task_t *child_task) /* OUT */ ! 915: { ! 916: return KERN_FAILURE; ! 917: } ! 918: ! 919: /*ARGSUSED*/ ! 920: kern_return_t ! 921: norma_task_teleport( ! 922: task_t parent_task, ! 923: boolean_t inherit_memory, ! 924: int child_node, ! 925: task_t *child_task) /* OUT */ ! 926: { ! 927: return KERN_FAILURE; ! 928: } ! 929: #endif /* NORMA_TASK */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.