xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 1991-2016 Free Software Foundation, Inc. |
| 2 | This file is part of the GNU C Library. |
| 3 | |
| 4 | The GNU C Library is free software; you can redistribute it and/or |
| 5 | modify it under the terms of the GNU Lesser General Public |
| 6 | License as published by the Free Software Foundation; either |
| 7 | version 2.1 of the License, or (at your option) any later version. |
| 8 | |
| 9 | The GNU C Library is distributed in the hope that it will be useful, |
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | Lesser General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU Lesser General Public |
| 15 | License along with the GNU C Library; if not, see |
| 16 | <http://www.gnu.org/licenses/>. */ |
| 17 | |
| 18 | #include <mach.h> |
| 19 | #include <thread_state.h> |
| 20 | #include <string.h> |
| 21 | #include <mach/machine/vm_param.h> |
| 22 | #include "sysdep.h" /* Defines stack direction. */ |
| 23 | |
| 24 | #define STACK_SIZE (16 * 1024 * 1024) /* 16MB, arbitrary. */ |
| 25 | |
| 26 | /* Give THREAD a stack and set it to run at PC when resumed. |
| 27 | If *STACK_SIZE is nonzero, that size of stack is allocated. |
| 28 | If *STACK_BASE is nonzero, that stack location is used. |
| 29 | If STACK_BASE is not null it is filled in with the chosen stack base. |
| 30 | If STACK_SIZE is not null it is filled in with the chosen stack size. |
| 31 | Regardless, an extra page of red zone is allocated off the end; this |
| 32 | is not included in *STACK_SIZE. */ |
| 33 | |
| 34 | kern_return_t |
| 35 | __mach_setup_thread (task_t task, thread_t thread, void *pc, |
| 36 | vm_address_t *stack_base, vm_size_t *stack_size) |
| 37 | { |
| 38 | kern_return_t error; |
| 39 | struct machine_thread_state ts; |
| 40 | mach_msg_type_number_t tssize = MACHINE_THREAD_STATE_COUNT; |
| 41 | vm_address_t stack; |
| 42 | vm_size_t size; |
| 43 | int anywhere; |
| 44 | |
| 45 | size = stack_size ? *stack_size ? : STACK_SIZE : STACK_SIZE; |
| 46 | stack = stack_base ? *stack_base ? : 0 : 0; |
| 47 | anywhere = !stack_base || !*stack_base; |
| 48 | |
| 49 | error = __vm_allocate (task, &stack, size + __vm_page_size, anywhere); |
| 50 | if (error) |
| 51 | return error; |
| 52 | |
| 53 | if (stack_size) |
| 54 | *stack_size = size; |
| 55 | |
| 56 | memset (&ts, 0, sizeof (ts)); |
| 57 | MACHINE_THREAD_STATE_SET_PC (&ts, pc); |
| 58 | #ifdef STACK_GROWTH_DOWN |
| 59 | if (stack_base) |
| 60 | *stack_base = stack + __vm_page_size; |
| 61 | ts.SP = stack + __vm_page_size + size; |
| 62 | #elif defined (STACK_GROWTH_UP) |
| 63 | if (stack_base) |
| 64 | *stack_base = stack; |
| 65 | ts.SP = stack; |
| 66 | stack += size; |
| 67 | #else |
| 68 | #error stack direction unknown |
| 69 | #endif |
| 70 | |
| 71 | /* Create the red zone. */ |
| 72 | if (error = __vm_protect (task, stack, __vm_page_size, 0, VM_PROT_NONE)) |
| 73 | return error; |
| 74 | |
| 75 | return __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR, |
| 76 | (natural_t *) &ts, tssize); |
| 77 | } |
| 78 | |
| 79 | weak_alias (__mach_setup_thread, mach_setup_thread) |