aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef OS_BSD_VM_OS_BSD_HPP aoqi@0: #define OS_BSD_VM_OS_BSD_HPP aoqi@0: aoqi@0: // Bsd_OS defines the interface to Bsd operating systems aoqi@0: aoqi@0: // Information about the protection of the page at address '0' on this os. aoqi@0: static bool zero_page_read_protected() { return true; } aoqi@0: aoqi@0: /* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */ aoqi@0: typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); aoqi@0: aoqi@0: #ifdef __APPLE__ aoqi@0: // Mac OS X doesn't support clock_gettime. Stub out the type, it is aoqi@0: // unused aoqi@0: typedef int clockid_t; aoqi@0: #endif aoqi@0: aoqi@0: class Bsd { aoqi@0: friend class os; aoqi@0: aoqi@0: // For signal-chaining aoqi@0: #define MAXSIGNUM 32 aoqi@0: static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions aoqi@0: static unsigned int sigs; // mask of signals that have aoqi@0: // preinstalled signal handlers aoqi@0: static bool libjsig_is_loaded; // libjsig that interposes sigaction(), aoqi@0: // __sigaction(), signal() is loaded aoqi@0: static struct sigaction *(*get_signal_action)(int); aoqi@0: static struct sigaction *get_preinstalled_handler(int); aoqi@0: static void save_preinstalled_handler(int, struct sigaction&); aoqi@0: aoqi@0: static void check_signal_handler(int sig); aoqi@0: aoqi@0: // For signal flags diagnostics aoqi@0: static int sigflags[MAXSIGNUM]; aoqi@0: aoqi@0: #ifdef __APPLE__ aoqi@0: // mach_absolute_time aoqi@0: static mach_timebase_info_data_t _timebase_info; aoqi@0: static volatile uint64_t _max_abstime; aoqi@0: #else aoqi@0: static int (*_clock_gettime)(clockid_t, struct timespec *); aoqi@0: #endif aoqi@0: aoqi@0: static GrowableArray* _cpu_to_node; aoqi@0: aoqi@0: protected: aoqi@0: aoqi@0: static julong _physical_memory; aoqi@0: static pthread_t _main_thread; aoqi@0: static int _page_size; aoqi@0: aoqi@0: static julong available_memory(); aoqi@0: static julong physical_memory() { return _physical_memory; } aoqi@0: static void initialize_system_info(); aoqi@0: aoqi@0: static bool supports_variable_stack_size(); aoqi@0: aoqi@0: static void rebuild_cpu_to_node_map(); aoqi@0: static GrowableArray* cpu_to_node() { return _cpu_to_node; } aoqi@0: aoqi@0: static bool hugetlbfs_sanity_check(bool warn, size_t page_size); aoqi@0: aoqi@0: public: aoqi@0: aoqi@0: static void init_thread_fpu_state(); aoqi@0: static pthread_t main_thread(void) { return _main_thread; } aoqi@0: aoqi@0: static void hotspot_sigmask(Thread* thread); aoqi@0: aoqi@0: static bool is_initial_thread(void); aoqi@0: static pid_t gettid(); aoqi@0: aoqi@0: static int page_size(void) { return _page_size; } aoqi@0: static void set_page_size(int val) { _page_size = val; } aoqi@0: aoqi@0: static address ucontext_get_pc(ucontext_t* uc); aoqi@0: static intptr_t* ucontext_get_sp(ucontext_t* uc); aoqi@0: static intptr_t* ucontext_get_fp(ucontext_t* uc); aoqi@0: aoqi@0: // For Analyzer Forte AsyncGetCallTrace profiling support: aoqi@0: // aoqi@0: // This interface should be declared in os_bsd_i486.hpp, but aoqi@0: // that file provides extensions to the os class and not the aoqi@0: // Bsd class. aoqi@0: static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc, aoqi@0: intptr_t** ret_sp, intptr_t** ret_fp); aoqi@0: aoqi@0: // This boolean allows users to forward their own non-matching signals aoqi@0: // to JVM_handle_bsd_signal, harmlessly. aoqi@0: static bool signal_handlers_are_installed; aoqi@0: aoqi@0: static int get_our_sigflags(int); aoqi@0: static void set_our_sigflags(int, int); aoqi@0: static void signal_sets_init(); aoqi@0: static void install_signal_handlers(); aoqi@0: static void set_signal_handler(int, bool); aoqi@0: static bool is_sig_ignored(int sig); aoqi@0: aoqi@0: static sigset_t* unblocked_signals(); aoqi@0: static sigset_t* vm_signals(); aoqi@0: static sigset_t* allowdebug_blocked_signals(); aoqi@0: aoqi@0: // For signal-chaining aoqi@0: static struct sigaction *get_chained_signal_action(int sig); aoqi@0: static bool chained_handler(int sig, siginfo_t* siginfo, void* context); aoqi@0: aoqi@0: // Minimum stack size a thread can be created with (allowing aoqi@0: // the VM to completely create the thread and enter user code) aoqi@0: static size_t min_stack_allowed; aoqi@0: aoqi@0: // Return default stack size or guard size for the specified thread type aoqi@0: static size_t default_stack_size(os::ThreadType thr_type); aoqi@0: static size_t default_guard_size(os::ThreadType thr_type); aoqi@0: aoqi@0: // Real-time clock functions aoqi@0: static void clock_init(void); aoqi@0: aoqi@0: static inline bool supports_monotonic_clock() { aoqi@0: #ifdef __APPLE__ aoqi@0: return true; aoqi@0: #else aoqi@0: return _clock_gettime != NULL; aoqi@0: #endif aoqi@0: } aoqi@0: aoqi@0: // Stack repair handling aoqi@0: aoqi@0: // none present aoqi@0: aoqi@0: // BsdThreads work-around for 6292965 aoqi@0: static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); aoqi@0: aoqi@0: private: aoqi@0: typedef int (*sched_getcpu_func_t)(void); aoqi@0: typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); aoqi@0: typedef int (*numa_max_node_func_t)(void); aoqi@0: typedef int (*numa_available_func_t)(void); aoqi@0: typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); aoqi@0: typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); aoqi@0: aoqi@0: static sched_getcpu_func_t _sched_getcpu; aoqi@0: static numa_node_to_cpus_func_t _numa_node_to_cpus; aoqi@0: static numa_max_node_func_t _numa_max_node; aoqi@0: static numa_available_func_t _numa_available; aoqi@0: static numa_tonode_memory_func_t _numa_tonode_memory; aoqi@0: static numa_interleave_memory_func_t _numa_interleave_memory; aoqi@0: static unsigned long* _numa_all_nodes; aoqi@0: aoqi@0: static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } aoqi@0: static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } aoqi@0: static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } aoqi@0: static void set_numa_available(numa_available_func_t func) { _numa_available = func; } aoqi@0: static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } aoqi@0: static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } aoqi@0: static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } aoqi@0: public: aoqi@0: static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } aoqi@0: static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { aoqi@0: return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1; aoqi@0: } aoqi@0: static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; } aoqi@0: static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; } aoqi@0: static int numa_tonode_memory(void *start, size_t size, int node) { aoqi@0: return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; aoqi@0: } aoqi@0: static void numa_interleave_memory(void *start, size_t size) { aoqi@0: if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) { aoqi@0: _numa_interleave_memory(start, size, _numa_all_nodes); aoqi@0: } aoqi@0: } aoqi@0: static int get_node_by_cpu(int cpu_id); aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class PlatformEvent : public CHeapObj { aoqi@0: private: aoqi@0: double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line aoqi@0: volatile int _Event ; aoqi@0: volatile int _nParked ; aoqi@0: pthread_mutex_t _mutex [1] ; aoqi@0: pthread_cond_t _cond [1] ; aoqi@0: double PostPad [2] ; aoqi@0: Thread * _Assoc ; aoqi@0: aoqi@0: public: // TODO-FIXME: make dtor private aoqi@0: ~PlatformEvent() { guarantee (0, "invariant") ; } aoqi@0: aoqi@0: public: aoqi@0: PlatformEvent() { aoqi@0: int status; aoqi@0: status = pthread_cond_init (_cond, NULL); aoqi@0: assert_status(status == 0, status, "cond_init"); aoqi@0: status = pthread_mutex_init (_mutex, NULL); aoqi@0: assert_status(status == 0, status, "mutex_init"); aoqi@0: _Event = 0 ; aoqi@0: _nParked = 0 ; aoqi@0: _Assoc = NULL ; aoqi@0: } aoqi@0: aoqi@0: // Use caution with reset() and fired() -- they may require MEMBARs aoqi@0: void reset() { _Event = 0 ; } aoqi@0: int fired() { return _Event; } aoqi@0: void park () ; aoqi@0: void unpark () ; aoqi@0: int TryPark () ; aoqi@0: int park (jlong millis) ; aoqi@0: void SetAssociation (Thread * a) { _Assoc = a ; } aoqi@0: }; aoqi@0: aoqi@0: class PlatformParker : public CHeapObj { aoqi@0: protected: aoqi@0: pthread_mutex_t _mutex [1] ; aoqi@0: pthread_cond_t _cond [1] ; aoqi@0: aoqi@0: public: // TODO-FIXME: make dtor private aoqi@0: ~PlatformParker() { guarantee (0, "invariant") ; } aoqi@0: aoqi@0: public: aoqi@0: PlatformParker() { aoqi@0: int status; aoqi@0: status = pthread_cond_init (_cond, NULL); aoqi@0: assert_status(status == 0, status, "cond_init"); aoqi@0: status = pthread_mutex_init (_mutex, NULL); aoqi@0: assert_status(status == 0, status, "mutex_init"); aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: #endif // OS_BSD_VM_OS_BSD_HPP