1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Mach Operating System 30 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University 31 * All Rights Reserved. 32 * 33 * Permission to use, copy, modify and distribute this software and its 34 * documentation is hereby granted, provided that both the copyright 35 * notice and this permission notice appear in all copies of the 36 * software, derivative works or modified versions, and any portions 37 * thereof, and that both notices appear in supporting documentation. 38 * 39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 42 * 43 * Carnegie Mellon requests users of this software to return to 44 * 45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 46 * School of Computer Science 47 * Carnegie Mellon University 48 * Pittsburgh PA 15213-3890 49 * 50 * any improvements or extensions that they make and grant Carnegie Mellon 51 * the rights to redistribute these changes. 52 */ 53 54#include <mach/mach.h> 55#include <mach/boolean.h> 56#include <mach/machine/ndr_def.h> 57#include <mach/mach_traps.h> 58#include <mach/mach_host.h> 59#include <mach/mach_init.h> 60#include <mach/vm_param.h> 61#include "externs.h" 62 63mach_port_t mach_task_self_ = MACH_PORT_NULL; 64mach_port_t mach_host_self_ = MACH_PORT_NULL; 65 66__private_extern__ kern_return_t _host_mach_msg_trap_return_; 67 68vm_size_t vm_page_size; 69vm_size_t vm_page_mask; 70int vm_page_shift; 71 72/* 73 * Forward internal declarations for automatic mach_init during 74 * fork() implementation. 75 */ 76/* fork() calls through atfork_child_routine */ 77void (*_atfork_child_routine)(void); 78 79static void mach_atfork_child_routine(void); 80static boolean_t first = TRUE; 81static void (*previous_atfork_child_routine)(void); 82static boolean_t mach_init_inited = FALSE; 83extern int mach_init(void); 84extern void _pthread_set_self(void *); 85extern void cthread_set_self(void *); 86extern void __libc_init(void); /* Libc initialization routine */ 87 88kern_return_t 89host_page_size(__unused host_t host, vm_size_t *out_page_size) 90{ 91 *out_page_size = PAGE_SIZE; 92 return KERN_SUCCESS; 93} 94 95static void mach_atfork_child_routine(void) 96{ 97 /* 98 * If an (*_atfork_child_routine)() was registered when 99 * mach_init was first called, then call that routine 100 * prior to performing our re-initialization. This ensures 101 * that the post-fork handlers are called in exactly the 102 * same order as the crt0 (exec) handlers. Any library 103 * that makes use of the _atfork_child_routine must follow 104 * the same technique. 105 */ 106 if (previous_atfork_child_routine) { 107 (*previous_atfork_child_routine)(); 108 } 109 mach_init_inited = FALSE; 110 mach_init(); 111} 112 113mach_port_t 114mach_host_self(void) 115{ 116 return(host_self_trap()); 117} 118 119int mach_init_doit(int forkchild) 120{ 121 host_t host; 122 123 /* 124 * Get the important ports into the cached values, 125 * as required by "mach_init.h". 126 */ 127 128 mach_task_self_ = task_self_trap(); 129 host = host_self_trap(); 130 131 132 if (!forkchild) { 133 /* 134 * Set up the post-fork child handler in the libc stub 135 * to invoke this routine if this process forks. Save the 136 * previous value in order that we can call that handler 137 * prior to performing our postfork work. 138 */ 139 140 first = FALSE; 141 previous_atfork_child_routine = _atfork_child_routine; 142 _atfork_child_routine = mach_atfork_child_routine; 143 _pthread_set_self(0); 144 cthread_set_self(0); 145 } 146 147 /* 148 * Initialize the single mig reply port 149 */ 150 151 mig_init(0); 152 153 /* 154 * Cache some other valuable system constants 155 */ 156 157 (void)host_page_size(host, &vm_page_size); 158 vm_page_mask = vm_page_size - 1; 159 if (vm_page_size == 0) { 160 /* guard against unlikely craziness */ 161 vm_page_shift = 0; 162 } else { 163 /* 164 * Unfortunately there's no kernel interface to get the 165 * vm_page_shift, but it's easy enough to calculate. 166 */ 167 for (vm_page_shift = 0; 168 (vm_page_size & (1 << vm_page_shift)) == 0; 169 vm_page_shift++) 170 continue; 171 } 172 173 mach_port_deallocate(mach_task_self_, host); 174 175 mach_init_ports(); 176 177#if WE_REALLY_NEED_THIS_GDB_HACK 178 /* 179 * Check to see if GDB wants us to stop 180 */ 181 { 182 task_user_data_data_t user_data; 183 mach_msg_type_number_t user_data_count = TASK_USER_DATA_COUNT; 184 185 user_data.user_data = 0; 186 (void)task_info(mach_task_self_, TASK_USER_DATA, 187 (task_info_t)&user_data, &user_data_count); 188#define MACH_GDB_RUN_MAGIC_NUMBER 1 189#ifdef MACH_GDB_RUN_MAGIC_NUMBER 190 /* This magic number is set in mach-aware gdb 191 * for RUN command to allow us to suspend user's 192 * executable (linked with this libmach!) 193 * with the code below. 194 * This hack should disappear when gdb improves. 195 */ 196 if ((int)user_data.user_data == MACH_GDB_RUN_MAGIC_NUMBER) { 197 kern_return_t ret; 198 user_data.user_data = 0; 199 200 ret = task_suspend (mach_task_self_); 201 if (ret != KERN_SUCCESS) { 202 while(1) (void)task_terminate(mach_task_self_); 203 } 204 } 205#undef MACH_GDB_RUN_MAGIC_NUMBER 206#endif /* MACH_GDB_RUN_MAGIC_NUMBER */ 207 } 208#endif /* WE_REALLY_NEED_THIS_GDB_HACK */ 209 210 /* 211 * Reserve page 0 so that the program doesn't get it as 212 * the result of a vm_allocate() or whatever. 213 */ 214 { 215 vm_offset_t zero_page_start; 216 217 zero_page_start = 0; 218 (void)vm_map(mach_task_self_, &zero_page_start, vm_page_size, 219 0, FALSE, MEMORY_OBJECT_NULL, 0, TRUE, 220 VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY); 221 /* ignore result, we don't care if it failed */ 222 } 223 224 return(0); 225} 226 227 228 229 230/* 231 * mach_init() is called explicitly in static executables (including dyld) 232 * It is called implicitly by libSystem_initializer() in dynamic executables 233 */ 234int mach_init(void) 235{ 236 int ret; 237 238 if (mach_init_inited) 239 return(0); 240 mach_init_inited = TRUE; 241 ret = mach_init_doit(0); 242 243 return ret; 244} 245 246 247 248 249/* called by _cthread_fork_child() */ 250int fork_mach_init(void) 251{ 252 /* called only from child */ 253 return(mach_init_doit(1)); 254} 255 256#undef mach_task_self 257 258mach_port_t 259mach_task_self(void) 260{ 261 return(task_self_trap()); 262} 263 264mach_port_t 265mach_thread_self(void) 266{ 267 return(thread_self_trap()); 268} 269