os_linux.hpp revision 844:bd02caa94611
1227825Stheraven/*
2227825Stheraven * Copyright 1999-2009 Sun Microsystems, Inc.  All Rights Reserved.
3227825Stheraven * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4227825Stheraven *
5227825Stheraven * This code is free software; you can redistribute it and/or modify it
6227825Stheraven * under the terms of the GNU General Public License version 2 only, as
7227825Stheraven * published by the Free Software Foundation.
8227825Stheraven *
9227825Stheraven * This code is distributed in the hope that it will be useful, but WITHOUT
10227825Stheraven * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11227825Stheraven * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12227825Stheraven * version 2 for more details (a copy is included in the LICENSE file that
13227825Stheraven * accompanied this code).
14227825Stheraven *
15227825Stheraven * You should have received a copy of the GNU General Public License version
16227825Stheraven * 2 along with this work; if not, write to the Free Software Foundation,
17227825Stheraven * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18227825Stheraven *
19227825Stheraven * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20227825Stheraven * CA 95054 USA or visit www.sun.com if you need additional information or
21227825Stheraven * have any questions.
22227825Stheraven *
23227825Stheraven */
24227825Stheraven
25227825Stheraven// Linux_OS defines the interface to Linux operating systems
26227825Stheraven
27227825Stheraven/* pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1 */
28227825Stheraventypedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
29227825Stheraven
30class Linux {
31  friend class os;
32
33  // For signal-chaining
34#define MAXSIGNUM 32
35  static struct sigaction sigact[MAXSIGNUM]; // saved preinstalled sigactions
36  static unsigned int sigs;             // mask of signals that have
37                                        // preinstalled signal handlers
38  static bool libjsig_is_loaded;        // libjsig that interposes sigaction(),
39                                        // __sigaction(), signal() is loaded
40  static struct sigaction *(*get_signal_action)(int);
41  static struct sigaction *get_preinstalled_handler(int);
42  static void save_preinstalled_handler(int, struct sigaction&);
43
44  static void check_signal_handler(int sig);
45
46  // For signal flags diagnostics
47  static int sigflags[MAXSIGNUM];
48
49  static int (*_clock_gettime)(clockid_t, struct timespec *);
50  static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
51
52  static address   _initial_thread_stack_bottom;
53  static uintptr_t _initial_thread_stack_size;
54
55  static const char *_glibc_version;
56  static const char *_libpthread_version;
57
58  static bool _is_floating_stack;
59  static bool _is_NPTL;
60  static bool _supports_fast_thread_cpu_time;
61
62  static GrowableArray<int>* _cpu_to_node;
63
64 protected:
65
66  static julong _physical_memory;
67  static pthread_t _main_thread;
68  static Mutex* _createThread_lock;
69  static int _page_size;
70
71  static julong available_memory();
72  static julong physical_memory() { return _physical_memory; }
73  static void initialize_system_info();
74
75  static void set_glibc_version(const char *s)      { _glibc_version = s; }
76  static void set_libpthread_version(const char *s) { _libpthread_version = s; }
77
78  static bool supports_variable_stack_size();
79
80  static void set_is_NPTL()                   { _is_NPTL = true;  }
81  static void set_is_LinuxThreads()           { _is_NPTL = false; }
82  static void set_is_floating_stack()         { _is_floating_stack = true; }
83
84  static void rebuild_cpu_to_node_map();
85  static GrowableArray<int>* cpu_to_node()    { return _cpu_to_node; }
86 public:
87  static void init_thread_fpu_state();
88  static int  get_fpu_control_word();
89  static void set_fpu_control_word(int fpu_control);
90  static pthread_t main_thread(void)                                { return _main_thread; }
91  // returns kernel thread id (similar to LWP id on Solaris), which can be
92  // used to access /proc
93  static pid_t gettid();
94  static void set_createThread_lock(Mutex* lk)                      { _createThread_lock = lk; }
95  static Mutex* createThread_lock(void)                             { return _createThread_lock; }
96  static void hotspot_sigmask(Thread* thread);
97
98  static address   initial_thread_stack_bottom(void)                { return _initial_thread_stack_bottom; }
99  static uintptr_t initial_thread_stack_size(void)                  { return _initial_thread_stack_size; }
100  static bool is_initial_thread(void);
101
102  static int page_size(void)                                        { return _page_size; }
103  static void set_page_size(int val)                                { _page_size = val; }
104
105  static address   ucontext_get_pc(ucontext_t* uc);
106  static intptr_t* ucontext_get_sp(ucontext_t* uc);
107  static intptr_t* ucontext_get_fp(ucontext_t* uc);
108
109  // For Analyzer Forte AsyncGetCallTrace profiling support:
110  //
111  // This interface should be declared in os_linux_i486.hpp, but
112  // that file provides extensions to the os class and not the
113  // Linux class.
114  static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
115    intptr_t** ret_sp, intptr_t** ret_fp);
116
117  // This boolean allows users to forward their own non-matching signals
118  // to JVM_handle_linux_signal, harmlessly.
119  static bool signal_handlers_are_installed;
120
121  static int get_our_sigflags(int);
122  static void set_our_sigflags(int, int);
123  static void signal_sets_init();
124  static void install_signal_handlers();
125  static void set_signal_handler(int, bool);
126  static bool is_sig_ignored(int sig);
127
128  static sigset_t* unblocked_signals();
129  static sigset_t* vm_signals();
130  static sigset_t* allowdebug_blocked_signals();
131
132  // For signal-chaining
133  static struct sigaction *get_chained_signal_action(int sig);
134  static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
135
136  // GNU libc and libpthread version strings
137  static const char *glibc_version()          { return _glibc_version; }
138  static const char *libpthread_version()     { return _libpthread_version; }
139
140  // NPTL or LinuxThreads?
141  static bool is_LinuxThreads()               { return !_is_NPTL; }
142  static bool is_NPTL()                       { return _is_NPTL;  }
143
144  // NPTL is always floating stack. LinuxThreads could be using floating
145  // stack or fixed stack.
146  static bool is_floating_stack()             { return _is_floating_stack; }
147
148  static void libpthread_init();
149  static bool libnuma_init();
150  static void* libnuma_dlsym(void* handle, const char* name);
151  // Minimum stack size a thread can be created with (allowing
152  // the VM to completely create the thread and enter user code)
153  static size_t min_stack_allowed;
154
155  // Return default stack size or guard size for the specified thread type
156  static size_t default_stack_size(os::ThreadType thr_type);
157  static size_t default_guard_size(os::ThreadType thr_type);
158
159  static void capture_initial_stack(size_t max_size);
160
161  // Stack overflow handling
162  static bool manually_expand_stack(JavaThread * t, address addr);
163  static int max_register_window_saves_before_flushing();
164
165  // Real-time clock functions
166  static void clock_init(void);
167
168  // fast POSIX clocks support
169  static void fast_thread_clock_init(void);
170
171  static bool supports_monotonic_clock() {
172    return _clock_gettime != NULL;
173  }
174
175  static int clock_gettime(clockid_t clock_id, struct timespec *tp) {
176    return _clock_gettime ? _clock_gettime(clock_id, tp) : -1;
177  }
178
179  static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) {
180    return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1;
181  }
182
183  static bool supports_fast_thread_cpu_time() {
184    return _supports_fast_thread_cpu_time;
185  }
186
187  static jlong fast_thread_cpu_time(clockid_t clockid);
188
189  // Stack repair handling
190
191  // none present
192
193  // LinuxThreads work-around for 6292965
194  static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
195
196
197  // Linux suspend/resume support - this helper is a shadow of its former
198  // self now that low-level suspension is barely used, and old workarounds
199  // for LinuxThreads are no longer needed.
200  class SuspendResume {
201  private:
202    volatile int _suspend_action;
203    // values for suspend_action:
204    #define SR_NONE               (0x00)
205    #define SR_SUSPEND            (0x01)  // suspend request
206    #define SR_CONTINUE           (0x02)  // resume request
207
208    volatile jint _state;
209    // values for _state: + SR_NONE
210    #define SR_SUSPENDED          (0x20)
211  public:
212    SuspendResume() { _suspend_action = SR_NONE; _state = SR_NONE; }
213
214    int suspend_action() const     { return _suspend_action; }
215    void set_suspend_action(int x) { _suspend_action = x;    }
216
217    // atomic updates for _state
218    void set_suspended()           {
219      jint temp, temp2;
220      do {
221        temp = _state;
222        temp2 = Atomic::cmpxchg(temp | SR_SUSPENDED, &_state, temp);
223      } while (temp2 != temp);
224    }
225    void clear_suspended()        {
226      jint temp, temp2;
227      do {
228        temp = _state;
229        temp2 = Atomic::cmpxchg(temp & ~SR_SUSPENDED, &_state, temp);
230      } while (temp2 != temp);
231    }
232    bool is_suspended()            { return _state & SR_SUSPENDED;       }
233
234    #undef SR_SUSPENDED
235  };
236
237private:
238  typedef int (*sched_getcpu_func_t)(void);
239  typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
240  typedef int (*numa_max_node_func_t)(void);
241  typedef int (*numa_available_func_t)(void);
242  typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);
243  typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);
244
245  static sched_getcpu_func_t _sched_getcpu;
246  static numa_node_to_cpus_func_t _numa_node_to_cpus;
247  static numa_max_node_func_t _numa_max_node;
248  static numa_available_func_t _numa_available;
249  static numa_tonode_memory_func_t _numa_tonode_memory;
250  static numa_interleave_memory_func_t _numa_interleave_memory;
251  static unsigned long* _numa_all_nodes;
252
253  static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }
254  static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }
255  static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }
256  static void set_numa_available(numa_available_func_t func) { _numa_available = func; }
257  static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
258  static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
259  static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
260public:
261  static int sched_getcpu()  { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
262  static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
263    return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1;
264  }
265  static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; }
266  static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; }
267  static int numa_tonode_memory(void *start, size_t size, int node) {
268    return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;
269  }
270  static void numa_interleave_memory(void *start, size_t size) {
271    if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) {
272      _numa_interleave_memory(start, size, _numa_all_nodes);
273    }
274  }
275  static int get_node_by_cpu(int cpu_id);
276};
277
278
279class PlatformEvent : public CHeapObj {
280  private:
281    double CachePad [4] ;   // increase odds that _mutex is sole occupant of cache line
282    volatile int _Event ;
283    volatile int _nParked ;
284    pthread_mutex_t _mutex  [1] ;
285    pthread_cond_t  _cond   [1] ;
286    double PostPad  [2] ;
287    Thread * _Assoc ;
288
289  public:       // TODO-FIXME: make dtor private
290    ~PlatformEvent() { guarantee (0, "invariant") ; }
291
292  public:
293    PlatformEvent() {
294      int status;
295      status = pthread_cond_init (_cond, NULL);
296      assert_status(status == 0, status, "cond_init");
297      status = pthread_mutex_init (_mutex, NULL);
298      assert_status(status == 0, status, "mutex_init");
299      _Event   = 0 ;
300      _nParked = 0 ;
301      _Assoc   = NULL ;
302    }
303
304    // Use caution with reset() and fired() -- they may require MEMBARs
305    void reset() { _Event = 0 ; }
306    int  fired() { return _Event; }
307    void park () ;
308    void unpark () ;
309    int  TryPark () ;
310    int  park (jlong millis) ;
311    void SetAssociation (Thread * a) { _Assoc = a ; }
312} ;
313
314class PlatformParker : public CHeapObj {
315  protected:
316    pthread_mutex_t _mutex [1] ;
317    pthread_cond_t  _cond  [1] ;
318
319  public:       // TODO-FIXME: make dtor private
320    ~PlatformParker() { guarantee (0, "invariant") ; }
321
322  public:
323    PlatformParker() {
324      int status;
325      status = pthread_cond_init (_cond, NULL);
326      assert_status(status == 0, status, "cond_init");
327      status = pthread_mutex_init (_mutex, NULL);
328      assert_status(status == 0, status, "mutex_init");
329    }
330} ;
331