Annotation of XNU/osfmk/kern/norma_task.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:  * 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 */

unix.superglobalmegacorp.com

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