]>
Commit | Line | Data |
---|---|---|
f1a1da6c A |
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 | */ | |
59 | void | |
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 * | |
145 | memset(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 | |
152 | bzero(void *s, size_t n) | |
153 | { | |
154 | _platform_bzero(s, n); | |
155 | } |