void ipc_task_init( task_t task, task_t parent) { ipc_space_t space; ipc_port_t kport; kern_return_t kr; int i; kr = ipc_space_create(&space); if (kr != KERN_SUCCESS) panic("ipc_task_init"); kport = ipc_port_alloc_kernel(); if (kport == IP_NULL) panic("ipc_task_init"); itk_lock_init(task); task->itk_self = kport; task->itk_sself = ipc_port_make_send(kport); task->itk_space = space; if (parent == TASK_NULL) { task->itk_exception = IP_NULL; task->itk_bootstrap = IP_NULL; for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) task->itk_registered[i] = IP_NULL; } else { itk_lock(parent); assert(parent->itk_self != IP_NULL); /* inherit registered ports */ for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) task->itk_registered[i] = ipc_port_copy_send(parent->itk_registered[i]); /* inherit exception and bootstrap ports */ task->itk_exception = ipc_port_copy_send(parent->itk_exception); task->itk_bootstrap = ipc_port_copy_send(parent->itk_bootstrap); itk_unlock(parent); } }
void ipc_task_init( task_t task, task_t parent) { ipc_space_t space; ipc_port_t kport; ipc_port_t nport; kern_return_t kr; int i; kr = ipc_space_create(&ipc_table_entries[0], &space); if (kr != KERN_SUCCESS) panic("ipc_task_init"); space->is_task = task; kport = ipc_port_alloc_kernel(); if (kport == IP_NULL) panic("ipc_task_init"); nport = ipc_port_alloc_kernel(); if (nport == IP_NULL) panic("ipc_task_init"); itk_lock_init(task); task->itk_self = kport; task->itk_nself = nport; task->itk_resume = IP_NULL; /* Lazily allocated on-demand */ task->itk_sself = ipc_port_make_send(kport); task->itk_debug_control = IP_NULL; task->itk_space = space; if (parent == TASK_NULL) { ipc_port_t port; for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) { task->exc_actions[i].port = IP_NULL; }/* for */ kr = host_get_host_port(host_priv_self(), &port); assert(kr == KERN_SUCCESS); task->itk_host = port; task->itk_bootstrap = IP_NULL; task->itk_seatbelt = IP_NULL; task->itk_gssd = IP_NULL; task->itk_task_access = IP_NULL; for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) task->itk_registered[i] = IP_NULL; } else { itk_lock(parent); assert(parent->itk_self != IP_NULL); /* inherit registered ports */ for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) task->itk_registered[i] = ipc_port_copy_send(parent->itk_registered[i]); /* inherit exception and bootstrap ports */ for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) { task->exc_actions[i].port = ipc_port_copy_send(parent->exc_actions[i].port); task->exc_actions[i].flavor = parent->exc_actions[i].flavor; task->exc_actions[i].behavior = parent->exc_actions[i].behavior; task->exc_actions[i].privileged = parent->exc_actions[i].privileged; }/* for */ task->itk_host = ipc_port_copy_send(parent->itk_host); task->itk_bootstrap = ipc_port_copy_send(parent->itk_bootstrap); task->itk_seatbelt = ipc_port_copy_send(parent->itk_seatbelt); task->itk_gssd = ipc_port_copy_send(parent->itk_gssd); task->itk_task_access = ipc_port_copy_send(parent->itk_task_access); itk_unlock(parent); } }
kern_return_t norma_task_common( task_t parent_task, boolean_t inherit_memory, boolean_t clone, boolean_t kill_parent, int child_node, task_t *child_task) { ipc_port_t remote_task, remote_host; task_t new_task; kern_return_t kr; int vector_start; unsigned int entry_vector_count; ipc_port_t bootstrap; emulation_vector_t entry_vector; ipc_port_t registered[TASK_PORT_REGISTER_MAX]; exception_mask_t exc_masks[EXC_TYPES_COUNT]; ipc_port_t exc_ports[EXC_TYPES_COUNT]; exception_behavior_t exc_behaviors[EXC_TYPES_COUNT]; thread_state_flavor_t exc_flavors[EXC_TYPES_COUNT]; unsigned count, exc_count; #if DIPC if (!dipc_node_is_valid (child_node)) { return KERN_INVALID_ARGUMENT; } if (child_node == dipc_node_self()) { if (clone) { /* * Cloning: easy if kill_parent; * (currently) impossible otherwise. */ if (kill_parent) { /* * Just return the parent -- nothing says that * the clone has to be a different task. */ *child_task = parent_task; return KERN_SUCCESS; } else { /* * XXX * There is no local call we can use with the * same memory semantics -- we'd have to * modify task_create_local, and vm_map_fork. * Not hard, just probably unnecessary except * for orthogonality. */ return KERN_INVALID_ARGUMENT; } } else { /* * Not cloning: just use task_create_local, * and task_terminate if appropriate. */ kr = task_create_local(parent_task, inherit_memory, FALSE, child_task); if (kr != KERN_SUCCESS) { return kr; } if (kill_parent) { kr = task_terminate(parent_task); if (kr != KERN_SUCCESS) { /* cleanup */ (void) task_terminate(*child_task); return kr; } } return KERN_SUCCESS; } } kr = task_get_emulation_vector(parent_task, &vector_start, &entry_vector, &entry_vector_count); if (kr != KERN_SUCCESS) { printf("task_get_emulation_vector failed: kr %d %x\n", kr, kr); return kr; } kr = task_get_inherited_ports(parent_task, &bootstrap, registered, &count, exc_masks, &exc_count, exc_ports, exc_behaviors, exc_flavors); if (kr != KERN_SUCCESS) { printf("task_get_inherited_ports failed: kr %d %x\n", kr, kr); return kr; } remote_host = dipc_host_priv_port(child_node); if (remote_host == IP_NULL) { panic("norma_task_create: no priv port for node %d\n", child_node); return KERN_INVALID_ARGUMENT; } kr = r_norma_task_allocate(remote_host, vector_start, entry_vector, entry_vector_count, bootstrap, registered, count, exc_masks, exc_count, exc_ports, exc_behaviors, exc_flavors, &remote_task); if (kr != KERN_SUCCESS) { return kr; } if (inherit_memory) { task_copy_vm(remote_host, parent_task->map, clone, kill_parent, remote_task); } if (kill_parent) { (void) task_terminate(parent_task); } /* * Create a placeholder task for the benefit of convert_task_to_port. * Set new_task->map to VM_MAP_NULL so that task_deallocate will * know that this is only a placeholder task. */ new_task = (task_t) zalloc(task_zone); if (new_task == TASK_NULL) { panic("task_create: no memory for task structure"); } #if MCMSG new_task->mcmsg_task = 0; #endif /* MCMSG */ /* only one ref, for our caller */ new_task->ref_count = 1; new_task->map = VM_MAP_NULL; new_task->itk_self = remote_task; mutex_init(&new_task->lock, ETAP_NORMA_TASK); itk_lock_init(new_task); *child_task = new_task; return(KERN_SUCCESS); #else /* DIPC */ printf("norma_task_common: no underlying transport!\n"); return KERN_INVALID_ARGUMENT; #endif /* DIPC */ }