Path: blob/master/src/hotspot/os/linux/os_linux.hpp
64440 views
/*1* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef OS_LINUX_OS_LINUX_HPP25#define OS_LINUX_OS_LINUX_HPP2627// Linux_OS defines the interface to Linux operating systems2829// Information about the protection of the page at address '0' on this os.30static bool zero_page_read_protected() { return true; }3132class Linux {33friend class CgroupSubsystem;34friend class os;35friend class OSContainer;36friend class TestReserveMemorySpecial;3738static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);39static int (*_pthread_setname_np)(pthread_t, const char*);4041static address _initial_thread_stack_bottom;42static uintptr_t _initial_thread_stack_size;4344static const char *_libc_version;45static const char *_libpthread_version;4647static bool _supports_fast_thread_cpu_time;4849static GrowableArray<int>* _cpu_to_node;50static GrowableArray<int>* _nindex_to_node;5152static size_t _default_large_page_size;5354protected:5556static julong _physical_memory;57static pthread_t _main_thread;58static int _page_size;5960static julong available_memory();61static julong physical_memory() { return _physical_memory; }62static void set_physical_memory(julong phys_mem) { _physical_memory = phys_mem; }63static int active_processor_count();6465static void initialize_system_info();6667static int commit_memory_impl(char* addr, size_t bytes, bool exec);68static int commit_memory_impl(char* addr, size_t bytes,69size_t alignment_hint, bool exec);7071static void set_libc_version(const char *s) { _libc_version = s; }72static void set_libpthread_version(const char *s) { _libpthread_version = s; }7374static void rebuild_cpu_to_node_map();75static void rebuild_nindex_to_node_map();76static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; }77static GrowableArray<int>* nindex_to_node() { return _nindex_to_node; }7879static size_t default_large_page_size();80static size_t scan_default_large_page_size();81static os::PageSizes scan_multiple_page_support();8283static bool setup_large_page_type(size_t page_size);84static bool transparent_huge_pages_sanity_check(bool warn, size_t pages_size);85static bool hugetlbfs_sanity_check(bool warn, size_t page_size);86static bool shm_hugetlbfs_sanity_check(bool warn, size_t page_size);8788static int hugetlbfs_page_size_flag(size_t page_size);8990static char* reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec);91static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec);92static bool commit_memory_special(size_t bytes, size_t page_size, char* req_addr, bool exec);9394static bool release_memory_special_impl(char* base, size_t bytes);95static bool release_memory_special_shm(char* base, size_t bytes);96static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);9798static void print_process_memory_info(outputStream* st);99static void print_system_memory_info(outputStream* st);100static bool print_container_info(outputStream* st);101static void print_steal_info(outputStream* st);102static void print_distro_info(outputStream* st);103static void print_libversion_info(outputStream* st);104static void print_proc_sys_info(outputStream* st);105static bool print_ld_preload_file(outputStream* st);106static void print_uptime_info(outputStream* st);107108public:109struct CPUPerfTicks {110uint64_t used;111uint64_t usedKernel;112uint64_t total;113uint64_t steal;114bool has_steal_ticks;115};116117// which_logical_cpu=-1 returns accumulated ticks for all cpus.118static bool get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu);119static bool _stack_is_executable;120static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);121static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);122static const char *dll_path(void* lib);123124static void init_thread_fpu_state();125static int get_fpu_control_word();126static void set_fpu_control_word(int fpu_control);127static pthread_t main_thread(void) { return _main_thread; }128// returns kernel thread id (similar to LWP id on Solaris), which can be129// used to access /proc130static pid_t gettid();131132static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }133static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }134135static int page_size(void) { return _page_size; }136static void set_page_size(int val) { _page_size = val; }137138static intptr_t* ucontext_get_sp(const ucontext_t* uc);139static intptr_t* ucontext_get_fp(const ucontext_t* uc);140141// GNU libc and libpthread version strings142static const char *libc_version() { return _libc_version; }143static const char *libpthread_version() { return _libpthread_version; }144145static void libpthread_init();146static void sched_getcpu_init();147static bool libnuma_init();148static void* libnuma_dlsym(void* handle, const char* name);149// libnuma v2 (libnuma_1.2) symbols150static void* libnuma_v2_dlsym(void* handle, const char* name);151152// Return default guard size for the specified thread type153static size_t default_guard_size(os::ThreadType thr_type);154155static void capture_initial_stack(size_t max_size);156157// Stack overflow handling158static bool manually_expand_stack(JavaThread * t, address addr);159160// fast POSIX clocks support161static void fast_thread_clock_init(void);162163static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) {164return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1;165}166167static bool supports_fast_thread_cpu_time() {168return _supports_fast_thread_cpu_time;169}170171static jlong fast_thread_cpu_time(clockid_t clockid);172173// Determine if the vmid is the parent pid for a child in a PID namespace.174// Return the namespace pid if so, otherwise -1.175static int get_namespace_pid(int vmid);176177// Output structure for query_process_memory_info()178struct meminfo_t {179ssize_t vmsize; // current virtual size180ssize_t vmpeak; // peak virtual size181ssize_t vmrss; // current resident set size182ssize_t vmhwm; // peak resident set size183ssize_t vmswap; // swapped out184ssize_t rssanon; // resident set size (anonymous mappings, needs 4.5)185ssize_t rssfile; // resident set size (file mappings, needs 4.5)186ssize_t rssshmem; // resident set size (shared mappings, needs 4.5)187};188189// Attempts to query memory information about the current process and return it in the output structure.190// May fail (returns false) or succeed (returns true) but not all output fields are available; unavailable191// fields will contain -1.192static bool query_process_memory_info(meminfo_t* info);193194// Stack repair handling195196// none present197198private:199static void numa_init();200static void expand_stack_to(address bottom);201202typedef int (*sched_getcpu_func_t)(void);203typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);204typedef int (*numa_node_to_cpus_v2_func_t)(int node, void *mask);205typedef int (*numa_max_node_func_t)(void);206typedef int (*numa_num_configured_nodes_func_t)(void);207typedef int (*numa_available_func_t)(void);208typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);209typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);210typedef void (*numa_interleave_memory_v2_func_t)(void *start, size_t size, struct bitmask* mask);211typedef struct bitmask* (*numa_get_membind_func_t)(void);212typedef struct bitmask* (*numa_get_interleave_mask_func_t)(void);213typedef long (*numa_move_pages_func_t)(int pid, unsigned long count, void **pages, const int *nodes, int *status, int flags);214typedef void (*numa_set_preferred_func_t)(int node);215typedef void (*numa_set_bind_policy_func_t)(int policy);216typedef int (*numa_bitmask_isbitset_func_t)(struct bitmask *bmp, unsigned int n);217typedef int (*numa_distance_func_t)(int node1, int node2);218219static sched_getcpu_func_t _sched_getcpu;220static numa_node_to_cpus_func_t _numa_node_to_cpus;221static numa_node_to_cpus_v2_func_t _numa_node_to_cpus_v2;222static numa_max_node_func_t _numa_max_node;223static numa_num_configured_nodes_func_t _numa_num_configured_nodes;224static numa_available_func_t _numa_available;225static numa_tonode_memory_func_t _numa_tonode_memory;226static numa_interleave_memory_func_t _numa_interleave_memory;227static numa_interleave_memory_v2_func_t _numa_interleave_memory_v2;228static numa_set_bind_policy_func_t _numa_set_bind_policy;229static numa_bitmask_isbitset_func_t _numa_bitmask_isbitset;230static numa_distance_func_t _numa_distance;231static numa_get_membind_func_t _numa_get_membind;232static numa_get_interleave_mask_func_t _numa_get_interleave_mask;233static numa_move_pages_func_t _numa_move_pages;234static numa_set_preferred_func_t _numa_set_preferred;235static unsigned long* _numa_all_nodes;236static struct bitmask* _numa_all_nodes_ptr;237static struct bitmask* _numa_nodes_ptr;238static struct bitmask* _numa_interleave_bitmask;239static struct bitmask* _numa_membind_bitmask;240241static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }242static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }243static void set_numa_node_to_cpus_v2(numa_node_to_cpus_v2_func_t func) { _numa_node_to_cpus_v2 = func; }244static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }245static void set_numa_num_configured_nodes(numa_num_configured_nodes_func_t func) { _numa_num_configured_nodes = func; }246static void set_numa_available(numa_available_func_t func) { _numa_available = func; }247static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }248static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }249static void set_numa_interleave_memory_v2(numa_interleave_memory_v2_func_t func) { _numa_interleave_memory_v2 = func; }250static void set_numa_set_bind_policy(numa_set_bind_policy_func_t func) { _numa_set_bind_policy = func; }251static void set_numa_bitmask_isbitset(numa_bitmask_isbitset_func_t func) { _numa_bitmask_isbitset = func; }252static void set_numa_distance(numa_distance_func_t func) { _numa_distance = func; }253static void set_numa_get_membind(numa_get_membind_func_t func) { _numa_get_membind = func; }254static void set_numa_get_interleave_mask(numa_get_interleave_mask_func_t func) { _numa_get_interleave_mask = func; }255static void set_numa_move_pages(numa_move_pages_func_t func) { _numa_move_pages = func; }256static void set_numa_set_preferred(numa_set_preferred_func_t func) { _numa_set_preferred = func; }257static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }258static void set_numa_all_nodes_ptr(struct bitmask **ptr) { _numa_all_nodes_ptr = (ptr == NULL ? NULL : *ptr); }259static void set_numa_nodes_ptr(struct bitmask **ptr) { _numa_nodes_ptr = (ptr == NULL ? NULL : *ptr); }260static void set_numa_interleave_bitmask(struct bitmask* ptr) { _numa_interleave_bitmask = ptr ; }261static void set_numa_membind_bitmask(struct bitmask* ptr) { _numa_membind_bitmask = ptr ; }262static int sched_getcpu_syscall(void);263264enum NumaAllocationPolicy{265NotInitialized,266Membind,267Interleave268};269static NumaAllocationPolicy _current_numa_policy;270271#ifdef __GLIBC__272struct glibc_mallinfo {273int arena;274int ordblks;275int smblks;276int hblks;277int hblkhd;278int usmblks;279int fsmblks;280int uordblks;281int fordblks;282int keepcost;283};284285struct glibc_mallinfo2 {286size_t arena;287size_t ordblks;288size_t smblks;289size_t hblks;290size_t hblkhd;291size_t usmblks;292size_t fsmblks;293size_t uordblks;294size_t fordblks;295size_t keepcost;296};297298typedef struct glibc_mallinfo (*mallinfo_func_t)(void);299typedef struct glibc_mallinfo2 (*mallinfo2_func_t)(void);300301static mallinfo_func_t _mallinfo;302static mallinfo2_func_t _mallinfo2;303#endif304305public:306static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }307static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen);308static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; }309static int numa_num_configured_nodes() {310return _numa_num_configured_nodes != NULL ? _numa_num_configured_nodes() : -1;311}312static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; }313static int numa_tonode_memory(void *start, size_t size, int node) {314return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;315}316317static bool is_running_in_interleave_mode() {318return _current_numa_policy == Interleave;319}320321static void set_configured_numa_policy(NumaAllocationPolicy numa_policy) {322_current_numa_policy = numa_policy;323}324325static NumaAllocationPolicy identify_numa_policy() {326for (int node = 0; node <= Linux::numa_max_node(); node++) {327if (Linux::_numa_bitmask_isbitset(Linux::_numa_interleave_bitmask, node)) {328return Interleave;329}330}331return Membind;332}333334static void numa_interleave_memory(void *start, size_t size) {335// Prefer v2 API336if (_numa_interleave_memory_v2 != NULL) {337if (is_running_in_interleave_mode()) {338_numa_interleave_memory_v2(start, size, _numa_interleave_bitmask);339} else if (_numa_membind_bitmask != NULL) {340_numa_interleave_memory_v2(start, size, _numa_membind_bitmask);341}342} else if (_numa_interleave_memory != NULL) {343_numa_interleave_memory(start, size, _numa_all_nodes);344}345}346static void numa_set_preferred(int node) {347if (_numa_set_preferred != NULL) {348_numa_set_preferred(node);349}350}351static void numa_set_bind_policy(int policy) {352if (_numa_set_bind_policy != NULL) {353_numa_set_bind_policy(policy);354}355}356static int numa_distance(int node1, int node2) {357return _numa_distance != NULL ? _numa_distance(node1, node2) : -1;358}359static long numa_move_pages(int pid, unsigned long count, void **pages, const int *nodes, int *status, int flags) {360return _numa_move_pages != NULL ? _numa_move_pages(pid, count, pages, nodes, status, flags) : -1;361}362static int get_node_by_cpu(int cpu_id);363static int get_existing_num_nodes();364// Check if numa node is configured (non-zero memory node).365static bool is_node_in_configured_nodes(unsigned int n) {366if (_numa_bitmask_isbitset != NULL && _numa_all_nodes_ptr != NULL) {367return _numa_bitmask_isbitset(_numa_all_nodes_ptr, n);368} else369return false;370}371// Check if numa node exists in the system (including zero memory nodes).372static bool is_node_in_existing_nodes(unsigned int n) {373if (_numa_bitmask_isbitset != NULL && _numa_nodes_ptr != NULL) {374return _numa_bitmask_isbitset(_numa_nodes_ptr, n);375} else if (_numa_bitmask_isbitset != NULL && _numa_all_nodes_ptr != NULL) {376// Not all libnuma API v2 implement numa_nodes_ptr, so it's not possible377// to trust the API version for checking its absence. On the other hand,378// numa_nodes_ptr found in libnuma 2.0.9 and above is the only way to get379// a complete view of all numa nodes in the system, hence numa_nodes_ptr380// is used to handle CPU and nodes on architectures (like PowerPC) where381// there can exist nodes with CPUs but no memory or vice-versa and the382// nodes may be non-contiguous. For most of the architectures, like383// x86_64, numa_node_ptr presents the same node set as found in384// numa_all_nodes_ptr so it's possible to use numa_all_nodes_ptr as a385// substitute.386return _numa_bitmask_isbitset(_numa_all_nodes_ptr, n);387} else388return false;389}390// Check if node is in bound node set.391static bool is_node_in_bound_nodes(int node) {392if (_numa_bitmask_isbitset != NULL) {393if (is_running_in_interleave_mode()) {394return _numa_bitmask_isbitset(_numa_interleave_bitmask, node);395} else {396return _numa_membind_bitmask != NULL ? _numa_bitmask_isbitset(_numa_membind_bitmask, node) : false;397}398}399return false;400}401// Check if bound to only one numa node.402// Returns true if bound to a single numa node, otherwise returns false.403static bool is_bound_to_single_node() {404int nodes = 0;405unsigned int node = 0;406unsigned int highest_node_number = 0;407408if (_numa_membind_bitmask != NULL && _numa_max_node != NULL && _numa_bitmask_isbitset != NULL) {409highest_node_number = _numa_max_node();410} else {411return false;412}413414for (node = 0; node <= highest_node_number; node++) {415if (_numa_bitmask_isbitset(_numa_membind_bitmask, node)) {416nodes++;417}418}419420if (nodes == 1) {421return true;422} else {423return false;424}425}426427static const GrowableArray<int>* numa_nindex_to_node() {428return _nindex_to_node;429}430};431432#endif // OS_LINUX_OS_LINUX_HPP433434435