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