1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/os/bsd/vm/os_bsd.hpp Sun Sep 25 16:03:29 2011 -0700 1.3 @@ -0,0 +1,368 @@ 1.4 +/* 1.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#ifndef OS_BSD_VM_OS_BSD_HPP 1.29 +#define OS_BSD_VM_OS_BSD_HPP 1.30 + 1.31 +// Bsd_OS defines the interface to Bsd operating systems 1.32 + 1.33 +/* pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1 */ 1.34 +typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *); 1.35 + 1.36 +#ifdef __APPLE__ 1.37 +// Mac OS X doesn't support clock_gettime. Stub out the type, it is 1.38 +// unused 1.39 +typedef int clockid_t; 1.40 +#endif 1.41 + 1.42 +class Bsd { 1.43 + friend class os; 1.44 + 1.45 + // For signal-chaining 1.46 +#define MAXSIGNUM 32 1.47 + static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions 1.48 + static unsigned int sigs; // mask of signals that have 1.49 + // preinstalled signal handlers 1.50 + static bool libjsig_is_loaded; // libjsig that interposes sigaction(), 1.51 + // __sigaction(), signal() is loaded 1.52 + static struct sigaction *(*get_signal_action)(int); 1.53 + static struct sigaction *get_preinstalled_handler(int); 1.54 + static void save_preinstalled_handler(int, struct sigaction&); 1.55 + 1.56 + static void check_signal_handler(int sig); 1.57 + 1.58 + // For signal flags diagnostics 1.59 + static int sigflags[MAXSIGNUM]; 1.60 + 1.61 + static int (*_clock_gettime)(clockid_t, struct timespec *); 1.62 +#ifndef _ALLBSD_SOURCE 1.63 + static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *); 1.64 + 1.65 + static address _initial_thread_stack_bottom; 1.66 + static uintptr_t _initial_thread_stack_size; 1.67 + 1.68 + static const char *_glibc_version; 1.69 + static const char *_libpthread_version; 1.70 + 1.71 + static bool _is_floating_stack; 1.72 + static bool _is_NPTL; 1.73 + static bool _supports_fast_thread_cpu_time; 1.74 +#endif 1.75 + 1.76 + static GrowableArray<int>* _cpu_to_node; 1.77 + 1.78 + protected: 1.79 + 1.80 + static julong _physical_memory; 1.81 + static pthread_t _main_thread; 1.82 +#ifndef _ALLBSD_SOURCE 1.83 + static Mutex* _createThread_lock; 1.84 +#endif 1.85 + static int _page_size; 1.86 + 1.87 + static julong available_memory(); 1.88 + static julong physical_memory() { return _physical_memory; } 1.89 + static void initialize_system_info(); 1.90 + 1.91 +#ifndef _ALLBSD_SOURCE 1.92 + static void set_glibc_version(const char *s) { _glibc_version = s; } 1.93 + static void set_libpthread_version(const char *s) { _libpthread_version = s; } 1.94 +#endif 1.95 + 1.96 + static bool supports_variable_stack_size(); 1.97 + 1.98 +#ifndef _ALLBSD_SOURCE 1.99 + static void set_is_NPTL() { _is_NPTL = true; } 1.100 + static void set_is_BsdThreads() { _is_NPTL = false; } 1.101 + static void set_is_floating_stack() { _is_floating_stack = true; } 1.102 +#endif 1.103 + 1.104 + static void rebuild_cpu_to_node_map(); 1.105 + static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; } 1.106 + 1.107 + static bool hugetlbfs_sanity_check(bool warn, size_t page_size); 1.108 + 1.109 + public: 1.110 + 1.111 + static void init_thread_fpu_state(); 1.112 +#ifndef _ALLBSD_SOURCE 1.113 + static int get_fpu_control_word(); 1.114 + static void set_fpu_control_word(int fpu_control); 1.115 +#endif 1.116 + static pthread_t main_thread(void) { return _main_thread; } 1.117 + 1.118 +#ifndef _ALLBSD_SOURCE 1.119 + // returns kernel thread id (similar to LWP id on Solaris), which can be 1.120 + // used to access /proc 1.121 + static pid_t gettid(); 1.122 + static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; } 1.123 + static Mutex* createThread_lock(void) { return _createThread_lock; } 1.124 +#endif 1.125 + static void hotspot_sigmask(Thread* thread); 1.126 + 1.127 +#ifndef _ALLBSD_SOURCE 1.128 + static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; } 1.129 + static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; } 1.130 +#endif 1.131 + static bool is_initial_thread(void); 1.132 + 1.133 + static int page_size(void) { return _page_size; } 1.134 + static void set_page_size(int val) { _page_size = val; } 1.135 + 1.136 + static address ucontext_get_pc(ucontext_t* uc); 1.137 + static intptr_t* ucontext_get_sp(ucontext_t* uc); 1.138 + static intptr_t* ucontext_get_fp(ucontext_t* uc); 1.139 + 1.140 + // For Analyzer Forte AsyncGetCallTrace profiling support: 1.141 + // 1.142 + // This interface should be declared in os_bsd_i486.hpp, but 1.143 + // that file provides extensions to the os class and not the 1.144 + // Bsd class. 1.145 + static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc, 1.146 + intptr_t** ret_sp, intptr_t** ret_fp); 1.147 + 1.148 + // This boolean allows users to forward their own non-matching signals 1.149 + // to JVM_handle_bsd_signal, harmlessly. 1.150 + static bool signal_handlers_are_installed; 1.151 + 1.152 + static int get_our_sigflags(int); 1.153 + static void set_our_sigflags(int, int); 1.154 + static void signal_sets_init(); 1.155 + static void install_signal_handlers(); 1.156 + static void set_signal_handler(int, bool); 1.157 + static bool is_sig_ignored(int sig); 1.158 + 1.159 + static sigset_t* unblocked_signals(); 1.160 + static sigset_t* vm_signals(); 1.161 + static sigset_t* allowdebug_blocked_signals(); 1.162 + 1.163 + // For signal-chaining 1.164 + static struct sigaction *get_chained_signal_action(int sig); 1.165 + static bool chained_handler(int sig, siginfo_t* siginfo, void* context); 1.166 + 1.167 +#ifndef _ALLBSD_SOURCE 1.168 + // GNU libc and libpthread version strings 1.169 + static const char *glibc_version() { return _glibc_version; } 1.170 + static const char *libpthread_version() { return _libpthread_version; } 1.171 + 1.172 + // NPTL or BsdThreads? 1.173 + static bool is_BsdThreads() { return !_is_NPTL; } 1.174 + static bool is_NPTL() { return _is_NPTL; } 1.175 + 1.176 + // NPTL is always floating stack. BsdThreads could be using floating 1.177 + // stack or fixed stack. 1.178 + static bool is_floating_stack() { return _is_floating_stack; } 1.179 + 1.180 + static void libpthread_init(); 1.181 + static bool libnuma_init(); 1.182 + static void* libnuma_dlsym(void* handle, const char* name); 1.183 +#endif 1.184 + // Minimum stack size a thread can be created with (allowing 1.185 + // the VM to completely create the thread and enter user code) 1.186 + static size_t min_stack_allowed; 1.187 + 1.188 + // Return default stack size or guard size for the specified thread type 1.189 + static size_t default_stack_size(os::ThreadType thr_type); 1.190 + static size_t default_guard_size(os::ThreadType thr_type); 1.191 + 1.192 +#ifndef _ALLBSD_SOURCE 1.193 + static void capture_initial_stack(size_t max_size); 1.194 + 1.195 + // Stack overflow handling 1.196 + static bool manually_expand_stack(JavaThread * t, address addr); 1.197 + static int max_register_window_saves_before_flushing(); 1.198 +#endif 1.199 + 1.200 + // Real-time clock functions 1.201 + static void clock_init(void); 1.202 + 1.203 +#ifndef _ALLBSD_SOURCE 1.204 + // fast POSIX clocks support 1.205 + static void fast_thread_clock_init(void); 1.206 +#endif 1.207 + 1.208 + static bool supports_monotonic_clock() { 1.209 + return _clock_gettime != NULL; 1.210 + } 1.211 + 1.212 + static int clock_gettime(clockid_t clock_id, struct timespec *tp) { 1.213 + return _clock_gettime ? _clock_gettime(clock_id, tp) : -1; 1.214 + } 1.215 + 1.216 +#ifndef _ALLBSD_SOURCE 1.217 + static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) { 1.218 + return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1; 1.219 + } 1.220 + 1.221 + static bool supports_fast_thread_cpu_time() { 1.222 + return _supports_fast_thread_cpu_time; 1.223 + } 1.224 + 1.225 + static jlong fast_thread_cpu_time(clockid_t clockid); 1.226 +#endif 1.227 + 1.228 + // Stack repair handling 1.229 + 1.230 + // none present 1.231 + 1.232 + // BsdThreads work-around for 6292965 1.233 + static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); 1.234 + 1.235 + 1.236 + // Bsd suspend/resume support - this helper is a shadow of its former 1.237 + // self now that low-level suspension is barely used, and old workarounds 1.238 + // for BsdThreads are no longer needed. 1.239 + class SuspendResume { 1.240 + private: 1.241 + volatile int _suspend_action; 1.242 + // values for suspend_action: 1.243 + #define SR_NONE (0x00) 1.244 + #define SR_SUSPEND (0x01) // suspend request 1.245 + #define SR_CONTINUE (0x02) // resume request 1.246 + 1.247 + volatile jint _state; 1.248 + // values for _state: + SR_NONE 1.249 + #define SR_SUSPENDED (0x20) 1.250 + public: 1.251 + SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; } 1.252 + 1.253 + int suspend_action() const { return _suspend_action; } 1.254 + void set_suspend_action(int x) { _suspend_action = x; } 1.255 + 1.256 + // atomic updates for _state 1.257 + void set_suspended() { 1.258 + jint temp, temp2; 1.259 + do { 1.260 + temp = _state; 1.261 + temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp); 1.262 + } while (temp2 != temp); 1.263 + } 1.264 + void clear_suspended() { 1.265 + jint temp, temp2; 1.266 + do { 1.267 + temp = _state; 1.268 + temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp); 1.269 + } while (temp2 != temp); 1.270 + } 1.271 + bool is_suspended() { return _state & SR_SUSPENDED; } 1.272 + 1.273 + #undef SR_SUSPENDED 1.274 + }; 1.275 + 1.276 +private: 1.277 + typedef int (*sched_getcpu_func_t)(void); 1.278 + typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); 1.279 + typedef int (*numa_max_node_func_t)(void); 1.280 + typedef int (*numa_available_func_t)(void); 1.281 + typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); 1.282 + typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); 1.283 + 1.284 + static sched_getcpu_func_t _sched_getcpu; 1.285 + static numa_node_to_cpus_func_t _numa_node_to_cpus; 1.286 + static numa_max_node_func_t _numa_max_node; 1.287 + static numa_available_func_t _numa_available; 1.288 + static numa_tonode_memory_func_t _numa_tonode_memory; 1.289 + static numa_interleave_memory_func_t _numa_interleave_memory; 1.290 + static unsigned long* _numa_all_nodes; 1.291 + 1.292 + static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } 1.293 + static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } 1.294 + static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } 1.295 + static void set_numa_available(numa_available_func_t func) { _numa_available = func; } 1.296 + static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } 1.297 + static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } 1.298 + static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } 1.299 +public: 1.300 + static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } 1.301 + static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { 1.302 + return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1; 1.303 + } 1.304 + static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; } 1.305 + static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; } 1.306 + static int numa_tonode_memory(void *start, size_t size, int node) { 1.307 + return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; 1.308 + } 1.309 + static void numa_interleave_memory(void *start, size_t size) { 1.310 + if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) { 1.311 + _numa_interleave_memory(start, size, _numa_all_nodes); 1.312 + } 1.313 + } 1.314 + static int get_node_by_cpu(int cpu_id); 1.315 +}; 1.316 + 1.317 + 1.318 +class PlatformEvent : public CHeapObj { 1.319 + private: 1.320 + double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line 1.321 + volatile int _Event ; 1.322 + volatile int _nParked ; 1.323 + pthread_mutex_t _mutex [1] ; 1.324 + pthread_cond_t _cond [1] ; 1.325 + double PostPad [2] ; 1.326 + Thread * _Assoc ; 1.327 + 1.328 + public: // TODO-FIXME: make dtor private 1.329 + ~PlatformEvent() { guarantee (0, "invariant") ; } 1.330 + 1.331 + public: 1.332 + PlatformEvent() { 1.333 + int status; 1.334 + status = pthread_cond_init (_cond, NULL); 1.335 + assert_status(status == 0, status, "cond_init"); 1.336 + status = pthread_mutex_init (_mutex, NULL); 1.337 + assert_status(status == 0, status, "mutex_init"); 1.338 + _Event = 0 ; 1.339 + _nParked = 0 ; 1.340 + _Assoc = NULL ; 1.341 + } 1.342 + 1.343 + // Use caution with reset() and fired() -- they may require MEMBARs 1.344 + void reset() { _Event = 0 ; } 1.345 + int fired() { return _Event; } 1.346 + void park () ; 1.347 + void unpark () ; 1.348 + int TryPark () ; 1.349 + int park (jlong millis) ; 1.350 + void SetAssociation (Thread * a) { _Assoc = a ; } 1.351 +} ; 1.352 + 1.353 +class PlatformParker : public CHeapObj { 1.354 + protected: 1.355 + pthread_mutex_t _mutex [1] ; 1.356 + pthread_cond_t _cond [1] ; 1.357 + 1.358 + public: // TODO-FIXME: make dtor private 1.359 + ~PlatformParker() { guarantee (0, "invariant") ; } 1.360 + 1.361 + public: 1.362 + PlatformParker() { 1.363 + int status; 1.364 + status = pthread_cond_init (_cond, NULL); 1.365 + assert_status(status == 0, status, "cond_init"); 1.366 + status = pthread_mutex_init (_mutex, NULL); 1.367 + assert_status(status == 0, status, "mutex_init"); 1.368 + } 1.369 +} ; 1.370 + 1.371 +#endif // OS_BSD_VM_OS_BSD_HPP