Serenity Operating System
at master 100 lines 3.4 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Assertions.h> 8#include <AK/Platform.h> 9#include <AK/StackInfo.h> 10#include <stdio.h> 11#include <string.h> 12 13#ifdef AK_OS_SERENITY 14# include <serenity.h> 15#elif defined(AK_OS_LINUX) or defined(AK_OS_MACOS) or defined(AK_OS_NETBSD) or defined(AK_OS_SOLARIS) 16# include <pthread.h> 17#elif defined(AK_OS_FREEBSD) or defined(AK_OS_OPENBSD) 18# include <pthread.h> 19# include <pthread_np.h> 20#elif defined(AK_OS_WINDOWS) 21# include <Windows.h> 22// NOTE: Prevent clang-format from re-ordering this header order 23# include <Processthreadsapi.h> 24#endif 25 26namespace AK { 27 28StackInfo::StackInfo() 29{ 30#ifdef AK_OS_SERENITY 31 if (get_stack_bounds(&m_base, &m_size) < 0) { 32 perror("get_stack_bounds"); 33 VERIFY_NOT_REACHED(); 34 } 35#elif defined(AK_OS_LINUX) or defined(AK_OS_FREEBSD) or defined(AK_OS_NETBSD) or defined(AK_OS_SOLARIS) 36 int rc; 37 pthread_attr_t attr; 38 pthread_attr_init(&attr); 39 40# ifdef AK_OS_LINUX 41 if ((rc = pthread_getattr_np(pthread_self(), &attr)) != 0) { 42 fprintf(stderr, "pthread_getattr_np: %s\n", strerror(rc)); 43 VERIFY_NOT_REACHED(); 44 } 45# else 46 if ((rc = pthread_attr_get_np(pthread_self(), &attr)) != 0) { 47 fprintf(stderr, "pthread_attr_get_np: %s\n", strerror(rc)); 48 VERIFY_NOT_REACHED(); 49 } 50# endif 51 52 if ((rc = pthread_attr_getstack(&attr, (void**)&m_base, &m_size)) != 0) { 53 fprintf(stderr, "pthread_attr_getstack: %s\n", strerror(rc)); 54 VERIFY_NOT_REACHED(); 55 } 56 pthread_attr_destroy(&attr); 57#elif defined(AK_OS_MACOS) 58 // NOTE: !! On MacOS, pthread_get_stackaddr_np gives the TOP of the stack, not the bottom! 59 FlatPtr top_of_stack = (FlatPtr)pthread_get_stackaddr_np(pthread_self()); 60 m_size = (size_t)pthread_get_stacksize_np(pthread_self()); 61 // https://github.com/rust-lang/rust/issues/43347#issuecomment-316783599 62 // https://developer.apple.com/library/archive/qa/qa1419/_index.html 63 // 64 // MacOS seems inconsistent on what stack size is given for the main thread. 65 // According to the Apple docs, default for main thread is 8MB, and default for 66 // other threads is 512KB 67 constexpr size_t eight_megabytes = 0x800000; 68 if (pthread_main_np() == 1 && m_size < eight_megabytes) { 69 // Assume no one messed with stack size linker options for the main thread, 70 // and just set it to 8MB. 71 m_size = eight_megabytes; 72 } 73 m_base = top_of_stack - m_size; 74#elif defined(AK_OS_OPENBSD) 75 int rc; 76 stack_t thread_stack; 77 if ((rc = pthread_stackseg_np(pthread_self(), &thread_stack)) != 0) { 78 fprintf(stderr, "pthread_stackseg_np: %s\n", strerror(rc)); 79 VERIFY_NOT_REACHED(); 80 } 81 FlatPtr top_of_stack = (FlatPtr)thread_stack.ss_sp; 82 m_size = (size_t)thread_stack.ss_size; 83 m_base = top_of_stack - m_size; 84#elif defined(AK_OS_WINDOWS) 85 ULONG_PTR low_limit = 0; 86 ULONG_PTR high_limit = 0; 87 GetCurrentThreadStackLimits(&low_limit, &high_limit); 88 89 m_base = static_cast<FlatPtr>(low_limit); 90 m_size = static_cast<size_t>(high_limit - low_limit); 91#else 92# pragma message "StackInfo not supported on this platform! Recursion checks and stack scans may not work properly" 93 m_size = (size_t)~0; 94 m_base = 0; 95#endif 96 97 m_top = m_base + m_size; 98} 99 100}