Path: blob/master/src/hotspot/os/linux/os_linux.hpp
40951 views
/*1* Copyright (c) 1999, 2021, 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);122123static void init_thread_fpu_state();124static int get_fpu_control_word();125static void set_fpu_control_word(int fpu_control);126static pthread_t main_thread(void) { return _main_thread; }127// returns kernel thread id (similar to LWP id on Solaris), which can be128// used to access /proc129static pid_t gettid();130131static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }132static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }133134static int page_size(void) { return _page_size; }135static void set_page_size(int val) { _page_size = val; }136137static intptr_t* ucontext_get_sp(const ucontext_t* uc);138static intptr_t* ucontext_get_fp(const ucontext_t* uc);139140// GNU libc and libpthread version strings141static const char *libc_version() { return _libc_version; }142static const char *libpthread_version() { return _libpthread_version; }143144static void libpthread_init();145static void sched_getcpu_init();146static bool libnuma_init();147static void* libnuma_dlsym(void* handle, const char* name);148// libnuma v2 (libnuma_1.2) symbols149static void* libnuma_v2_dlsym(void* handle, const char* name);150151// Return default guard size for the specified thread type152static size_t default_guard_size(os::ThreadType thr_type);153154static void capture_initial_stack(size_t max_size);155156// Stack overflow handling157static bool manually_expand_stack(JavaThread * t, address addr);158159// fast POSIX clocks support160static void fast_thread_clock_init(void);161162static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) {163return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1;164}165166static bool supports_fast_thread_cpu_time() {167return _supports_fast_thread_cpu_time;168}169170static jlong fast_thread_cpu_time(clockid_t clockid);171172// Determine if the vmid is the parent pid for a child in a PID namespace.173// Return the namespace pid if so, otherwise -1.174static int get_namespace_pid(int vmid);175176// Stack repair handling177178// none present179180private:181static void numa_init();182static void expand_stack_to(address bottom);183184typedef int (*sched_getcpu_func_t)(void);185typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);186typedef int (*numa_node_to_cpus_v2_func_t)(int node, void *mask);187typedef int (*numa_max_node_func_t)(void);188typedef int (*numa_num_configured_nodes_func_t)(void);189typedef int (*numa_available_func_t)(void);190typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);191typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);192typedef void (*numa_interleave_memory_v2_func_t)(void *start, size_t size, struct bitmask* mask);193typedef struct bitmask* (*numa_get_membind_func_t)(void);194typedef struct bitmask* (*numa_get_interleave_mask_func_t)(void);195typedef long (*numa_move_pages_func_t)(int pid, unsigned long count, void **pages, const int *nodes, int *status, int flags);196typedef void (*numa_set_preferred_func_t)(int node);197typedef void (*numa_set_bind_policy_func_t)(int policy);198typedef int (*numa_bitmask_isbitset_func_t)(struct bitmask *bmp, unsigned int n);199typedef int (*numa_distance_func_t)(int node1, int node2);200201static sched_getcpu_func_t _sched_getcpu;202static numa_node_to_cpus_func_t _numa_node_to_cpus;203static numa_node_to_cpus_v2_func_t _numa_node_to_cpus_v2;204static numa_max_node_func_t _numa_max_node;205static numa_num_configured_nodes_func_t _numa_num_configured_nodes;206static numa_available_func_t _numa_available;207static numa_tonode_memory_func_t _numa_tonode_memory;208static numa_interleave_memory_func_t _numa_interleave_memory;209static numa_interleave_memory_v2_func_t _numa_interleave_memory_v2;210static numa_set_bind_policy_func_t _numa_set_bind_policy;211static numa_bitmask_isbitset_func_t _numa_bitmask_isbitset;212static numa_distance_func_t _numa_distance;213static numa_get_membind_func_t _numa_get_membind;214static numa_get_interleave_mask_func_t _numa_get_interleave_mask;215static numa_move_pages_func_t _numa_move_pages;216static numa_set_preferred_func_t _numa_set_preferred;217static unsigned long* _numa_all_nodes;218static struct bitmask* _numa_all_nodes_ptr;219static struct bitmask* _numa_nodes_ptr;220static struct bitmask* _numa_interleave_bitmask;221static struct bitmask* _numa_membind_bitmask;222223static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }224static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }225static void set_numa_node_to_cpus_v2(numa_node_to_cpus_v2_func_t func) { _numa_node_to_cpus_v2 = func; }226static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }227static void set_numa_num_configured_nodes(numa_num_configured_nodes_func_t func) { _numa_num_configured_nodes = func; }228static void set_numa_available(numa_available_func_t func) { _numa_available = func; }229static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }230static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }231static void set_numa_interleave_memory_v2(numa_interleave_memory_v2_func_t func) { _numa_interleave_memory_v2 = func; }232static void set_numa_set_bind_policy(numa_set_bind_policy_func_t func) { _numa_set_bind_policy = func; }233static void set_numa_bitmask_isbitset(numa_bitmask_isbitset_func_t func) { _numa_bitmask_isbitset = func; }234static void set_numa_distance(numa_distance_func_t func) { _numa_distance = func; }235static void set_numa_get_membind(numa_get_membind_func_t func) { _numa_get_membind = func; }236static void set_numa_get_interleave_mask(numa_get_interleave_mask_func_t func) { _numa_get_interleave_mask = func; }237static void set_numa_move_pages(numa_move_pages_func_t func) { _numa_move_pages = func; }238static void set_numa_set_preferred(numa_set_preferred_func_t func) { _numa_set_preferred = func; }239static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }240static void set_numa_all_nodes_ptr(struct bitmask **ptr) { _numa_all_nodes_ptr = (ptr == NULL ? NULL : *ptr); }241static void set_numa_nodes_ptr(struct bitmask **ptr) { _numa_nodes_ptr = (ptr == NULL ? NULL : *ptr); }242static void set_numa_interleave_bitmask(struct bitmask* ptr) { _numa_interleave_bitmask = ptr ; }243static void set_numa_membind_bitmask(struct bitmask* ptr) { _numa_membind_bitmask = ptr ; }244static int sched_getcpu_syscall(void);245246enum NumaAllocationPolicy{247NotInitialized,248Membind,249Interleave250};251static NumaAllocationPolicy _current_numa_policy;252253#ifdef __GLIBC__254struct glibc_mallinfo {255int arena;256int ordblks;257int smblks;258int hblks;259int hblkhd;260int usmblks;261int fsmblks;262int uordblks;263int fordblks;264int keepcost;265};266267struct glibc_mallinfo2 {268size_t arena;269size_t ordblks;270size_t smblks;271size_t hblks;272size_t hblkhd;273size_t usmblks;274size_t fsmblks;275size_t uordblks;276size_t fordblks;277size_t keepcost;278};279280typedef struct glibc_mallinfo (*mallinfo_func_t)(void);281typedef struct glibc_mallinfo2 (*mallinfo2_func_t)(void);282283static mallinfo_func_t _mallinfo;284static mallinfo2_func_t _mallinfo2;285#endif286287public:288static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }289static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen);290static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; }291static int numa_num_configured_nodes() {292return _numa_num_configured_nodes != NULL ? _numa_num_configured_nodes() : -1;293}294static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; }295static int numa_tonode_memory(void *start, size_t size, int node) {296return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;297}298299static bool is_running_in_interleave_mode() {300return _current_numa_policy == Interleave;301}302303static void set_configured_numa_policy(NumaAllocationPolicy numa_policy) {304_current_numa_policy = numa_policy;305}306307static NumaAllocationPolicy identify_numa_policy() {308for (int node = 0; node <= Linux::numa_max_node(); node++) {309if (Linux::_numa_bitmask_isbitset(Linux::_numa_interleave_bitmask, node)) {310return Interleave;311}312}313return Membind;314}315316static void numa_interleave_memory(void *start, size_t size) {317// Prefer v2 API318if (_numa_interleave_memory_v2 != NULL) {319if (is_running_in_interleave_mode()) {320_numa_interleave_memory_v2(start, size, _numa_interleave_bitmask);321} else if (_numa_membind_bitmask != NULL) {322_numa_interleave_memory_v2(start, size, _numa_membind_bitmask);323}324} else if (_numa_interleave_memory != NULL) {325_numa_interleave_memory(start, size, _numa_all_nodes);326}327}328static void numa_set_preferred(int node) {329if (_numa_set_preferred != NULL) {330_numa_set_preferred(node);331}332}333static void numa_set_bind_policy(int policy) {334if (_numa_set_bind_policy != NULL) {335_numa_set_bind_policy(policy);336}337}338static int numa_distance(int node1, int node2) {339return _numa_distance != NULL ? _numa_distance(node1, node2) : -1;340}341static long numa_move_pages(int pid, unsigned long count, void **pages, const int *nodes, int *status, int flags) {342return _numa_move_pages != NULL ? _numa_move_pages(pid, count, pages, nodes, status, flags) : -1;343}344static int get_node_by_cpu(int cpu_id);345static int get_existing_num_nodes();346// Check if numa node is configured (non-zero memory node).347static bool is_node_in_configured_nodes(unsigned int n) {348if (_numa_bitmask_isbitset != NULL && _numa_all_nodes_ptr != NULL) {349return _numa_bitmask_isbitset(_numa_all_nodes_ptr, n);350} else351return false;352}353// Check if numa node exists in the system (including zero memory nodes).354static bool is_node_in_existing_nodes(unsigned int n) {355if (_numa_bitmask_isbitset != NULL && _numa_nodes_ptr != NULL) {356return _numa_bitmask_isbitset(_numa_nodes_ptr, n);357} else if (_numa_bitmask_isbitset != NULL && _numa_all_nodes_ptr != NULL) {358// Not all libnuma API v2 implement numa_nodes_ptr, so it's not possible359// to trust the API version for checking its absence. On the other hand,360// numa_nodes_ptr found in libnuma 2.0.9 and above is the only way to get361// a complete view of all numa nodes in the system, hence numa_nodes_ptr362// is used to handle CPU and nodes on architectures (like PowerPC) where363// there can exist nodes with CPUs but no memory or vice-versa and the364// nodes may be non-contiguous. For most of the architectures, like365// x86_64, numa_node_ptr presents the same node set as found in366// numa_all_nodes_ptr so it's possible to use numa_all_nodes_ptr as a367// substitute.368return _numa_bitmask_isbitset(_numa_all_nodes_ptr, n);369} else370return false;371}372// Check if node is in bound node set.373static bool is_node_in_bound_nodes(int node) {374if (_numa_bitmask_isbitset != NULL) {375if (is_running_in_interleave_mode()) {376return _numa_bitmask_isbitset(_numa_interleave_bitmask, node);377} else {378return _numa_membind_bitmask != NULL ? _numa_bitmask_isbitset(_numa_membind_bitmask, node) : false;379}380}381return false;382}383// Check if bound to only one numa node.384// Returns true if bound to a single numa node, otherwise returns false.385static bool is_bound_to_single_node() {386int nodes = 0;387struct bitmask* bmp = NULL;388unsigned int node = 0;389unsigned int highest_node_number = 0;390391if (_numa_get_membind != NULL && _numa_max_node != NULL && _numa_bitmask_isbitset != NULL) {392bmp = _numa_get_membind();393highest_node_number = _numa_max_node();394} else {395return false;396}397398for (node = 0; node <= highest_node_number; node++) {399if (_numa_bitmask_isbitset(bmp, node)) {400nodes++;401}402}403404if (nodes == 1) {405return true;406} else {407return false;408}409}410411static const GrowableArray<int>* numa_nindex_to_node() {412return _nindex_to_node;413}414};415416#endif // OS_LINUX_OS_LINUX_HPP417418419