< prev index next >

src/os/linux/vm/os_linux.cpp

Print this page
rev 12334 : 8169373: Work around linux NPTL stack guard error.
Summary: Also skip OS guard page for compiler thread, merge similar code on linux platforms, and streamline OS guard page handling on linuxs390, linuxppc, aixppc.


 706 
 707   // Allocate the OSThread object
 708   OSThread* osthread = new OSThread(NULL, NULL);
 709   if (osthread == NULL) {
 710     return false;
 711   }
 712 
 713   // set the correct thread state
 714   osthread->set_thread_type(thr_type);
 715 
 716   // Initial state is ALLOCATED but not INITIALIZED
 717   osthread->set_state(ALLOCATED);
 718 
 719   thread->set_osthread(osthread);
 720 
 721   // init thread attributes
 722   pthread_attr_t attr;
 723   pthread_attr_init(&attr);
 724   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 725 
 726   // calculate stack size if it's not specified by caller
 727   size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);







 728   pthread_attr_setstacksize(&attr, stack_size);
 729 
 730   // glibc guard page
 731   pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
 732 
 733   ThreadState state;
 734 
 735   {
 736     pthread_t tid;
 737     int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
 738 
 739     char buf[64];
 740     if (ret == 0) {
 741       log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
 742         (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
 743     } else {
 744       log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.",
 745         os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
 746     }
 747 


2823       set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
2824                                             libnuma_dlsym(handle, "numa_tonode_memory")));
2825       set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
2826                                                 libnuma_dlsym(handle, "numa_interleave_memory")));
2827       set_numa_set_bind_policy(CAST_TO_FN_PTR(numa_set_bind_policy_func_t,
2828                                               libnuma_dlsym(handle, "numa_set_bind_policy")));
2829 
2830 
2831       if (numa_available() != -1) {
2832         set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle, "numa_all_nodes"));
2833         // Create a cpu -> node mapping
2834         _cpu_to_node = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<int>(0, true);
2835         rebuild_cpu_to_node_map();
2836         return true;
2837       }
2838     }
2839   }
2840   return false;
2841 }
2842 







2843 // rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
2844 // The table is later used in get_node_by_cpu().
2845 void os::Linux::rebuild_cpu_to_node_map() {
2846   const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
2847                               // in libnuma (possible values are starting from 16,
2848                               // and continuing up with every other power of 2, but less
2849                               // than the maximum number of CPUs supported by kernel), and
2850                               // is a subject to change (in libnuma version 2 the requirements
2851                               // are more reasonable) we'll just hardcode the number they use
2852                               // in the library.
2853   const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
2854 
2855   size_t cpu_num = processor_count();
2856   size_t cpu_map_size = NCPUS / BitsPerCLong;
2857   size_t cpu_map_valid_size =
2858     MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
2859 
2860   cpu_to_node()->clear();
2861   cpu_to_node()->at_grow(cpu_num - 1);
2862   size_t node_num = numa_get_groups_num();


6054                "\n\n"
6055                "Do you want to debug the problem?\n\n"
6056                "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " UINTX_FORMAT " (" INTPTR_FORMAT ")\n"
6057                "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
6058                "Otherwise, press RETURN to abort...",
6059                os::current_process_id(), os::current_process_id(),
6060                os::current_thread_id(), os::current_thread_id());
6061 
6062   bool yes = os::message_box("Unexpected Error", buf);
6063 
6064   if (yes) {
6065     // yes, user asked VM to launch debugger
6066     jio_snprintf(buf, sizeof(char)*buflen, "gdb /proc/%d/exe %d",
6067                  os::current_process_id(), os::current_process_id());
6068 
6069     os::fork_and_exec(buf);
6070     yes = false;
6071   }
6072   return yes;
6073 }



























































































6074 
6075 static inline struct timespec get_mtime(const char* filename) {
6076   struct stat st;
6077   int ret = os::stat(filename, &st);
6078   assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno));
6079   return st.st_mtim;
6080 }
6081 
6082 int os::compare_file_modified_times(const char* file1, const char* file2) {
6083   struct timespec filetime1 = get_mtime(file1);
6084   struct timespec filetime2 = get_mtime(file2);
6085   int diff = filetime1.tv_sec - filetime2.tv_sec;
6086   if (diff == 0) {
6087     return filetime1.tv_nsec - filetime2.tv_nsec;
6088   }
6089   return diff;
6090 }
6091 
6092 /////////////// Unit tests ///////////////
6093 




 706 
 707   // Allocate the OSThread object
 708   OSThread* osthread = new OSThread(NULL, NULL);
 709   if (osthread == NULL) {
 710     return false;
 711   }
 712 
 713   // set the correct thread state
 714   osthread->set_thread_type(thr_type);
 715 
 716   // Initial state is ALLOCATED but not INITIALIZED
 717   osthread->set_state(ALLOCATED);
 718 
 719   thread->set_osthread(osthread);
 720 
 721   // init thread attributes
 722   pthread_attr_t attr;
 723   pthread_attr_init(&attr);
 724   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 725 
 726   // Calculate stack size if it's not specified by caller.
 727   size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);
 728   // In the Linux NPTL pthread implementation the guard size mechanism
 729   // is not implemented properly. The posix standard requires to add
 730   // the size of the guard pages to the stack size, instead Linux
 731   // takes the space out of 'stacksize'. Thus we adapt the requested
 732   // stack_size by the size of the guard pages to mimick proper
 733   // behaviour.
 734   stack_size = align_size_up(stack_size + os::Linux::default_guard_size(thr_type), vm_page_size());
 735   pthread_attr_setstacksize(&attr, stack_size);
 736 
 737   // glibc guard page
 738   pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
 739 
 740   ThreadState state;
 741 
 742   {
 743     pthread_t tid;
 744     int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
 745 
 746     char buf[64];
 747     if (ret == 0) {
 748       log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
 749         (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
 750     } else {
 751       log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.",
 752         os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
 753     }
 754 


2830       set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
2831                                             libnuma_dlsym(handle, "numa_tonode_memory")));
2832       set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
2833                                                 libnuma_dlsym(handle, "numa_interleave_memory")));
2834       set_numa_set_bind_policy(CAST_TO_FN_PTR(numa_set_bind_policy_func_t,
2835                                               libnuma_dlsym(handle, "numa_set_bind_policy")));
2836 
2837 
2838       if (numa_available() != -1) {
2839         set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle, "numa_all_nodes"));
2840         // Create a cpu -> node mapping
2841         _cpu_to_node = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<int>(0, true);
2842         rebuild_cpu_to_node_map();
2843         return true;
2844       }
2845     }
2846   }
2847   return false;
2848 }
2849 
2850 size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
2851   // Creating guard page is very expensive. Java thread has HotSpot
2852   // guard page, only enable glibc guard page for non-Java threads.
2853   // (Remember: compiler thread is a java thread, too!)
2854   return ((thr_type == java_thread || thr_type == os::compiler_thread) ? 0 : page_size());
2855 }
2856 
2857 // rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
2858 // The table is later used in get_node_by_cpu().
2859 void os::Linux::rebuild_cpu_to_node_map() {
2860   const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
2861                               // in libnuma (possible values are starting from 16,
2862                               // and continuing up with every other power of 2, but less
2863                               // than the maximum number of CPUs supported by kernel), and
2864                               // is a subject to change (in libnuma version 2 the requirements
2865                               // are more reasonable) we'll just hardcode the number they use
2866                               // in the library.
2867   const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
2868 
2869   size_t cpu_num = processor_count();
2870   size_t cpu_map_size = NCPUS / BitsPerCLong;
2871   size_t cpu_map_valid_size =
2872     MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
2873 
2874   cpu_to_node()->clear();
2875   cpu_to_node()->at_grow(cpu_num - 1);
2876   size_t node_num = numa_get_groups_num();


6068                "\n\n"
6069                "Do you want to debug the problem?\n\n"
6070                "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " UINTX_FORMAT " (" INTPTR_FORMAT ")\n"
6071                "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
6072                "Otherwise, press RETURN to abort...",
6073                os::current_process_id(), os::current_process_id(),
6074                os::current_thread_id(), os::current_thread_id());
6075 
6076   bool yes = os::message_box("Unexpected Error", buf);
6077 
6078   if (yes) {
6079     // yes, user asked VM to launch debugger
6080     jio_snprintf(buf, sizeof(char)*buflen, "gdb /proc/%d/exe %d",
6081                  os::current_process_id(), os::current_process_id());
6082 
6083     os::fork_and_exec(buf);
6084     yes = false;
6085   }
6086   return yes;
6087 }
6088 
6089 
6090 // Java/Compiler thread:
6091 //
6092 //   Low memory addresses
6093 // P0 +------------------------+
6094 //    |                        |\  JavaThread created by VM does not have glibc
6095 //    |    glibc guard page    | - guard, attached Java thread usually has
6096 //    |                        |/  1 page glibc guard.
6097 // P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
6098 //    |                        |\
6099 //    |  HotSpot Guard Pages   | - red and yellow pages
6100 //    |                        |/
6101 //    +------------------------+ JavaThread::stack_yellow_zone_base()
6102 //    |                        |\
6103 //    |      Normal Stack      | -
6104 //    |                        |/
6105 // P2 +------------------------+ Thread::stack_base()
6106 //
6107 // Non-Java thread:
6108 //
6109 //   Low memory addresses
6110 // P0 +------------------------+
6111 //    |                        |\
6112 //    |  glibc guard page      | - usually 1 page
6113 //    |                        |/
6114 // P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
6115 //    |                        |\
6116 //    |      Normal Stack      | -
6117 //    |                        |/
6118 // P2 +------------------------+ Thread::stack_base()
6119 //
6120 // ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
6121 //    pthread_attr_getstack()
6122 // ** Due to NPTL implementation error, linux takes the OS guard page out
6123 //    of the stack size given in pthread_attr. We work around this for
6124 //    threads created by the VM (We adapt bottom to be P1 and size accordingly.)
6125 //
6126 #ifndef ZERO
6127 static void current_stack_region(address * bottom, size_t * size) {
6128   if (os::Linux::is_initial_thread()) {
6129     // initial thread needs special handling because pthread_getattr_np()
6130     // may return bogus value.
6131     *bottom = os::Linux::initial_thread_stack_bottom();
6132     *size   = os::Linux::initial_thread_stack_size();
6133   } else {
6134     pthread_attr_t attr;
6135 
6136     int rslt = pthread_getattr_np(pthread_self(), &attr);
6137 
6138     // JVM needs to know exact stack location, abort if it fails
6139     if (rslt != 0) {
6140       if (rslt == ENOMEM) {
6141         vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
6142       } else {
6143         fatal("pthread_getattr_np failed with errno = %d", rslt);
6144       }
6145     }
6146 
6147     if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
6148       fatal("Can not locate current stack attributes!");
6149     }
6150 
6151     // Work around NPTL stack guard error.
6152     size_t guard_size = 0;
6153     pthread_attr_getguardsize(&attr, &guard_size);
6154     *bottom += guard_size;
6155     *size   -= guard_size;
6156 
6157     pthread_attr_destroy(&attr);
6158 
6159   }
6160   assert(os::current_stack_pointer() >= *bottom &&
6161          os::current_stack_pointer() < *bottom + *size, "just checking");
6162 }
6163 
6164 address os::current_stack_base() {
6165   address bottom;
6166   size_t size;
6167   current_stack_region(&bottom, &size);
6168   return (bottom + size);
6169 }
6170 
6171 size_t os::current_stack_size() {
6172   // stack size includes normal stack and HotSpot guard pages
6173   address bottom;
6174   size_t size;
6175   current_stack_region(&bottom, &size);
6176   return size;
6177 }
6178 #endif
6179 
6180 static inline struct timespec get_mtime(const char* filename) {
6181   struct stat st;
6182   int ret = os::stat(filename, &st);
6183   assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno));
6184   return st.st_mtim;
6185 }
6186 
6187 int os::compare_file_modified_times(const char* file1, const char* file2) {
6188   struct timespec filetime1 = get_mtime(file1);
6189   struct timespec filetime2 = get_mtime(file2);
6190   int diff = filetime1.tv_sec - filetime2.tv_sec;
6191   if (diff == 0) {
6192     return filetime1.tv_nsec - filetime2.tv_nsec;
6193   }
6194   return diff;
6195 }
6196 
6197 /////////////// Unit tests ///////////////
6198 


< prev index next >