1/* 2 * Copyright (c) 2000-2003, 2008, 2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 25 * All Rights Reserved 26 * 27 * Permission to use, copy, modify, and distribute this software and 28 * its documentation for any purpose and without fee is hereby granted, 29 * provided that the above copyright notice appears in all copies and 30 * that both the copyright notice and this permission notice appear in 31 * supporting documentation. 32 * 33 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35 * FOR A PARTICULAR PURPOSE. 36 * 37 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 * 43 */ 44/* 45 * MkLinux 46 */ 47 48/* 49 * Machine specific support for thread initialization 50 */ 51 52 53#include "internal.h" 54#include <platform/string.h> 55 56/* 57 * Set up the initial state of a MACH thread 58 */ 59void 60_pthread_setup(pthread_t thread, 61 void (*routine)(pthread_t), 62 void *vsp, 63 int suspended, 64 int needresume) 65{ 66#if defined(__i386__) 67 i386_thread_state_t state = {0}; 68 thread_state_flavor_t flavor = x86_THREAD_STATE32; 69 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; 70#elif defined(__x86_64__) 71 x86_thread_state64_t state = {0}; 72 thread_state_flavor_t flavor = x86_THREAD_STATE64; 73 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 74#elif defined(__arm__) 75 arm_thread_state_t state = {0}; 76 thread_state_flavor_t flavor = ARM_THREAD_STATE; 77 mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT; 78#else 79#error _pthread_setup not defined for this architecture 80#endif 81 82 if (suspended) { 83 (void)thread_get_state(_pthread_kernel_thread(thread), 84 flavor, 85 (thread_state_t)&state, 86 &count); 87 } 88 89#if defined(__i386__) 90 uintptr_t *sp = vsp; 91 92 state.__eip = (uintptr_t)routine; 93 94 // We need to simulate a 16-byte aligned stack frame as if we had 95 // executed a call instruction. Since we're "pushing" one argument, 96 // we need to adjust the pointer by 12 bytes (3 * sizeof (int *)) 97 sp -= 3; // make sure stack is aligned 98 *--sp = (uintptr_t)thread; // argument to function 99 *--sp = 0; // fake return address 100 state.__esp = (uintptr_t)sp; // set stack pointer 101#elif defined(__x86_64__) 102 uintptr_t *sp = vsp; 103 104 state.__rip = (uintptr_t)routine; 105 106 // We need to simulate a 16-byte aligned stack frame as if we had 107 // executed a call instruction. The stack should already be aligned 108 // before it comes to us and we don't need to push any arguments, 109 // so we shouldn't need to change it. 110 state.__rdi = (uintptr_t)thread; // argument to function 111 *--sp = 0; // fake return address 112 state.__rsp = (uintptr_t)sp; // set stack pointer 113#elif defined(__arm__) 114 state.__pc = (uintptr_t)routine; 115 116 // Detect switch to thumb mode. 117 if (state.__pc & 1) { 118 state.__pc &= ~1; 119 state.__cpsr |= 0x20; /* PSR_THUMB */ 120 } 121 122 state.__sp = (uintptr_t)vsp - C_ARGSAVE_LEN - C_RED_ZONE; 123 state.__r[0] = (uintptr_t)thread; 124#else 125#error _pthread_setup not defined for this architecture 126#endif 127 128 if (suspended) { 129 (void)thread_set_state(_pthread_kernel_thread(thread), flavor, (thread_state_t)&state, count); 130 if (needresume) { 131 (void)thread_resume(_pthread_kernel_thread(thread)); 132 } 133 } else { 134 mach_port_t kernel_thread; 135 (void)thread_create_running(mach_task_self(), flavor, (thread_state_t)&state, count, &kernel_thread); 136 _pthread_set_kernel_thread(thread, kernel_thread); 137 } 138} 139 140// pthread_setup initializes large structures to 0, which the compiler turns into a library call to memset. To avoid linking against 141// Libc, provide a simple wrapper that calls through to the libplatform primitives 142 143#undef memset 144__attribute__((visibility("hidden"))) void * 145memset(void *b, int c, size_t len) 146{ 147 return _platform_memset(b, c, len); 148} 149 150#undef bzero 151__attribute__((visibility("hidden"))) void 152bzero(void *s, size_t n) 153{ 154 _platform_bzero(s, n); 155} 156