src/hotspot/os/solaris/os_solaris.cpp
changeset 58654 562bf1878089
parent 58548 430b9a492a05
child 58679 9c3209ff7550
child 59016 3b9eeae66fa0
equal deleted inserted replaced
58653:71fef5fae9cc 58654:562bf1878089
   263   if (enabler) {
   263   if (enabler) {
   264     enabler(-1, -1);
   264     enabler(-1, -1);
   265   }
   265   }
   266 }
   266 }
   267 
   267 
   268 static int _processors_online = 0;
       
   269 
       
   270 jint os::Solaris::_os_thread_limit = 0;
   268 jint os::Solaris::_os_thread_limit = 0;
   271 volatile jint os::Solaris::_os_thread_count = 0;
   269 volatile jint os::Solaris::_os_thread_count = 0;
   272 
   270 
   273 julong os::available_memory() {
   271 julong os::available_memory() {
   274   return Solaris::available_memory();
   272   return Solaris::available_memory();
   289 static volatile hrtime_t max_hrtime = 0;
   287 static volatile hrtime_t max_hrtime = 0;
   290 
   288 
   291 
   289 
   292 void os::Solaris::initialize_system_info() {
   290 void os::Solaris::initialize_system_info() {
   293   set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
   291   set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
   294   _processors_online = sysconf(_SC_NPROCESSORS_ONLN);
       
   295   _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) *
   292   _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) *
   296                                      (julong)sysconf(_SC_PAGESIZE);
   293                                      (julong)sysconf(_SC_PAGESIZE);
   297 }
   294 }
   298 
   295 
   299 uint os::processor_id() {
   296 uint os::processor_id() {
   318   if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) {
   315   if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) {
   319     uint_t pset_cpus;
   316     uint_t pset_cpus;
   320     // Query the number of cpus available to us.
   317     // Query the number of cpus available to us.
   321     if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) {
   318     if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) {
   322       assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check");
   319       assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check");
   323       _processors_online = pset_cpus;
       
   324       return pset_cpus;
   320       return pset_cpus;
   325     }
   321     }
   326   }
   322   }
   327   // Otherwise return number of online cpus
   323   // Otherwise return number of online cpus
   328   return online_cpus;
   324   return online_cpus;
   329 }
       
   330 
       
   331 static bool find_processors_in_pset(psetid_t        pset,
       
   332                                     processorid_t** id_array,
       
   333                                     uint_t*         id_length) {
       
   334   bool result = false;
       
   335   // Find the number of processors in the processor set.
       
   336   if (pset_info(pset, NULL, id_length, NULL) == 0) {
       
   337     // Make up an array to hold their ids.
       
   338     *id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length, mtInternal);
       
   339     // Fill in the array with their processor ids.
       
   340     if (pset_info(pset, NULL, id_length, *id_array) == 0) {
       
   341       result = true;
       
   342     }
       
   343   }
       
   344   return result;
       
   345 }
       
   346 
       
   347 // Callers of find_processors_online() must tolerate imprecise results --
       
   348 // the system configuration can change asynchronously because of DR
       
   349 // or explicit psradm operations.
       
   350 //
       
   351 // We also need to take care that the loop (below) terminates as the
       
   352 // number of processors online can change between the _SC_NPROCESSORS_ONLN
       
   353 // request and the loop that builds the list of processor ids.   Unfortunately
       
   354 // there's no reliable way to determine the maximum valid processor id,
       
   355 // so we use a manifest constant, MAX_PROCESSOR_ID, instead.  See p_online
       
   356 // man pages, which claim the processor id set is "sparse, but
       
   357 // not too sparse".  MAX_PROCESSOR_ID is used to ensure that we eventually
       
   358 // exit the loop.
       
   359 //
       
   360 // In the future we'll be able to use sysconf(_SC_CPUID_MAX), but that's
       
   361 // not available on S8.0.
       
   362 
       
   363 static bool find_processors_online(processorid_t** id_array,
       
   364                                    uint*           id_length) {
       
   365   const processorid_t MAX_PROCESSOR_ID = 100000;
       
   366   // Find the number of processors online.
       
   367   *id_length = sysconf(_SC_NPROCESSORS_ONLN);
       
   368   // Make up an array to hold their ids.
       
   369   *id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length, mtInternal);
       
   370   // Processors need not be numbered consecutively.
       
   371   long found = 0;
       
   372   processorid_t next = 0;
       
   373   while (found < *id_length && next < MAX_PROCESSOR_ID) {
       
   374     processor_info_t info;
       
   375     if (processor_info(next, &info) == 0) {
       
   376       // NB, PI_NOINTR processors are effectively online ...
       
   377       if (info.pi_state == P_ONLINE || info.pi_state == P_NOINTR) {
       
   378         (*id_array)[found] = next;
       
   379         found += 1;
       
   380       }
       
   381     }
       
   382     next += 1;
       
   383   }
       
   384   if (found < *id_length) {
       
   385     // The loop above didn't identify the expected number of processors.
       
   386     // We could always retry the operation, calling sysconf(_SC_NPROCESSORS_ONLN)
       
   387     // and re-running the loop, above, but there's no guarantee of progress
       
   388     // if the system configuration is in flux.  Instead, we just return what
       
   389     // we've got.  Note that in the worst case find_processors_online() could
       
   390     // return an empty set.  (As a fall-back in the case of the empty set we
       
   391     // could just return the ID of the current processor).
       
   392     *id_length = found;
       
   393   }
       
   394 
       
   395   return true;
       
   396 }
       
   397 
       
   398 static bool assign_distribution(processorid_t* id_array,
       
   399                                 uint           id_length,
       
   400                                 uint*          distribution,
       
   401                                 uint           distribution_length) {
       
   402   // We assume we can assign processorid_t's to uint's.
       
   403   assert(sizeof(processorid_t) == sizeof(uint),
       
   404          "can't convert processorid_t to uint");
       
   405   // Quick check to see if we won't succeed.
       
   406   if (id_length < distribution_length) {
       
   407     return false;
       
   408   }
       
   409   // Assign processor ids to the distribution.
       
   410   // Try to shuffle processors to distribute work across boards,
       
   411   // assuming 4 processors per board.
       
   412   const uint processors_per_board = ProcessDistributionStride;
       
   413   // Find the maximum processor id.
       
   414   processorid_t max_id = 0;
       
   415   for (uint m = 0; m < id_length; m += 1) {
       
   416     max_id = MAX2(max_id, id_array[m]);
       
   417   }
       
   418   // The next id, to limit loops.
       
   419   const processorid_t limit_id = max_id + 1;
       
   420   // Make up markers for available processors.
       
   421   bool* available_id = NEW_C_HEAP_ARRAY(bool, limit_id, mtInternal);
       
   422   for (uint c = 0; c < limit_id; c += 1) {
       
   423     available_id[c] = false;
       
   424   }
       
   425   for (uint a = 0; a < id_length; a += 1) {
       
   426     available_id[id_array[a]] = true;
       
   427   }
       
   428   // Step by "boards", then by "slot", copying to "assigned".
       
   429   // NEEDS_CLEANUP: The assignment of processors should be stateful,
       
   430   //                remembering which processors have been assigned by
       
   431   //                previous calls, etc., so as to distribute several
       
   432   //                independent calls of this method.  What we'd like is
       
   433   //                It would be nice to have an API that let us ask
       
   434   //                how many processes are bound to a processor,
       
   435   //                but we don't have that, either.
       
   436   //                In the short term, "board" is static so that
       
   437   //                subsequent distributions don't all start at board 0.
       
   438   static uint board = 0;
       
   439   uint assigned = 0;
       
   440   // Until we've found enough processors ....
       
   441   while (assigned < distribution_length) {
       
   442     // ... find the next available processor in the board.
       
   443     for (uint slot = 0; slot < processors_per_board; slot += 1) {
       
   444       uint try_id = board * processors_per_board + slot;
       
   445       if ((try_id < limit_id) && (available_id[try_id] == true)) {
       
   446         distribution[assigned] = try_id;
       
   447         available_id[try_id] = false;
       
   448         assigned += 1;
       
   449         break;
       
   450       }
       
   451     }
       
   452     board += 1;
       
   453     if (board * processors_per_board + 0 >= limit_id) {
       
   454       board = 0;
       
   455     }
       
   456   }
       
   457   FREE_C_HEAP_ARRAY(bool, available_id);
       
   458   return true;
       
   459 }
   325 }
   460 
   326 
   461 void os::set_native_thread_name(const char *name) {
   327 void os::set_native_thread_name(const char *name) {
   462   if (Solaris::_pthread_setname_np != NULL) {
   328   if (Solaris::_pthread_setname_np != NULL) {
   463     // Only the first 31 bytes of 'name' are processed by pthread_setname_np
   329     // Only the first 31 bytes of 'name' are processed by pthread_setname_np
   466     char buf[32];
   332     char buf[32];
   467     snprintf(buf, sizeof(buf), "%s", name);
   333     snprintf(buf, sizeof(buf), "%s", name);
   468     buf[sizeof(buf) - 1] = '\0';
   334     buf[sizeof(buf) - 1] = '\0';
   469     Solaris::_pthread_setname_np(pthread_self(), buf);
   335     Solaris::_pthread_setname_np(pthread_self(), buf);
   470   }
   336   }
   471 }
       
   472 
       
   473 bool os::distribute_processes(uint length, uint* distribution) {
       
   474   bool result = false;
       
   475   // Find the processor id's of all the available CPUs.
       
   476   processorid_t* id_array  = NULL;
       
   477   uint           id_length = 0;
       
   478   // There are some races between querying information and using it,
       
   479   // since processor sets can change dynamically.
       
   480   psetid_t pset = PS_NONE;
       
   481   // Are we running in a processor set?
       
   482   if ((pset_bind(PS_QUERY, P_PID, P_MYID, &pset) == 0) && pset != PS_NONE) {
       
   483     result = find_processors_in_pset(pset, &id_array, &id_length);
       
   484   } else {
       
   485     result = find_processors_online(&id_array, &id_length);
       
   486   }
       
   487   if (result == true) {
       
   488     if (id_length >= length) {
       
   489       result = assign_distribution(id_array, id_length, distribution, length);
       
   490     } else {
       
   491       result = false;
       
   492     }
       
   493   }
       
   494   FREE_C_HEAP_ARRAY(processorid_t, id_array);
       
   495   return result;
       
   496 }
   337 }
   497 
   338 
   498 bool os::bind_to_processor(uint processor_id) {
   339 bool os::bind_to_processor(uint processor_id) {
   499   // We assume that a processorid_t can be stored in a uint.
   340   // We assume that a processorid_t can be stored in a uint.
   500   assert(sizeof(uint) == sizeof(processorid_t),
   341   assert(sizeof(uint) == sizeof(processorid_t),
  1235     return true;
  1076     return true;
  1236   }
  1077   }
  1237 }
  1078 }
  1238 
  1079 
  1239 bool os::supports_vtime() { return true; }
  1080 bool os::supports_vtime() { return true; }
  1240 bool os::enable_vtime() { return false; }
       
  1241 bool os::vtime_enabled() { return false; }
       
  1242 
  1081 
  1243 double os::elapsedVTime() {
  1082 double os::elapsedVTime() {
  1244   return (double)gethrvtime() / (double)hrtime_hz;
  1083   return (double)gethrvtime() / (double)hrtime_hz;
  1245 }
  1084 }
  1246 
  1085