|
|
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.