1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "asm/macroAssembler.inline.hpp"
  27 #include "memory/resourceArea.hpp"
  28 #include "runtime/java.hpp"
  29 #include "runtime/os.hpp"
  30 #include "runtime/stubCodeGenerator.hpp"
  31 #include "vm_version_sparc.hpp"
  32 
  33 int VM_Version::_features = VM_Version::unknown_m;
  34 const char* VM_Version::_features_str = "";
  35 
  36 void VM_Version::initialize() {
  37   _features = determine_features();
  38   PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
  39   PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
  40   PrefetchFieldsAhead         = prefetch_fields_ahead();
  41 
  42   assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 1, "invalid value");
  43   if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
  44   if( AllocatePrefetchInstr > 1 ) AllocatePrefetchInstr = 0;
  45 
  46   // Allocation prefetch settings
  47   intx cache_line_size = prefetch_data_size();
  48   if( cache_line_size > AllocatePrefetchStepSize )
  49     AllocatePrefetchStepSize = cache_line_size;
  50 
  51   assert(AllocatePrefetchLines > 0, "invalid value");
  52   if( AllocatePrefetchLines < 1 )     // set valid value in product VM
  53     AllocatePrefetchLines = 3;
  54   assert(AllocateInstancePrefetchLines > 0, "invalid value");
  55   if( AllocateInstancePrefetchLines < 1 ) // set valid value in product VM
  56     AllocateInstancePrefetchLines = 1;
  57 
  58   AllocatePrefetchDistance = allocate_prefetch_distance();
  59   AllocatePrefetchStyle    = allocate_prefetch_style();
  60 
  61   assert((AllocatePrefetchDistance % AllocatePrefetchStepSize) == 0 &&
  62          (AllocatePrefetchDistance > 0), "invalid value");
  63   if ((AllocatePrefetchDistance % AllocatePrefetchStepSize) != 0 ||
  64       (AllocatePrefetchDistance <= 0)) {
  65     AllocatePrefetchDistance = AllocatePrefetchStepSize;
  66   }
  67 
  68   if (AllocatePrefetchStyle == 3 && !has_blk_init()) {
  69     warning("BIS instructions are not available on this CPU");
  70     FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1);
  71   }
  72 
  73   guarantee(VM_Version::has_v9(), "only SPARC v9 is supported");
  74 
  75   assert(ArraycopySrcPrefetchDistance < 4096, "invalid value");
  76   if (ArraycopySrcPrefetchDistance >= 4096)
  77     ArraycopySrcPrefetchDistance = 4064;
  78   assert(ArraycopyDstPrefetchDistance < 4096, "invalid value");
  79   if (ArraycopyDstPrefetchDistance >= 4096)
  80     ArraycopyDstPrefetchDistance = 4064;
  81 
  82   UseSSE = 0; // Only on x86 and x64
  83 
  84   _supports_cx8 = has_v9();
  85   _supports_atomic_getset4 = true; // swap instruction
  86 
  87   // There are Fujitsu Sparc64 CPUs which support blk_init as well so
  88   // we have to take this check out of the 'is_niagara()' block below.
  89   if (has_blk_init()) {
  90     // When using CMS or G1, we cannot use memset() in BOT updates
  91     // because the sun4v/CMT version in libc_psr uses BIS which
  92     // exposes "phantom zeros" to concurrent readers. See 6948537.
  93     if (FLAG_IS_DEFAULT(UseMemSetInBOT) && (UseConcMarkSweepGC || UseG1GC)) {
  94       FLAG_SET_DEFAULT(UseMemSetInBOT, false);
  95     }
  96     // Issue a stern warning if the user has explicitly set
  97     // UseMemSetInBOT (it is known to cause issues), but allow
  98     // use for experimentation and debugging.
  99     if (UseConcMarkSweepGC || UseG1GC) {
 100       if (UseMemSetInBOT) {
 101         assert(!FLAG_IS_DEFAULT(UseMemSetInBOT), "Error");
 102         warning("Experimental flag -XX:+UseMemSetInBOT is known to cause instability"
 103                 " on sun4v; please understand that you are using at your own risk!");
 104       }
 105     }
 106   }
 107 
 108   if (is_niagara()) {
 109     // Indirect branch is the same cost as direct
 110     if (FLAG_IS_DEFAULT(UseInlineCaches)) {
 111       FLAG_SET_DEFAULT(UseInlineCaches, false);
 112     }
 113     // Align loops on a single instruction boundary.
 114     if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
 115       FLAG_SET_DEFAULT(OptoLoopAlignment, 4);
 116     }
 117 #ifdef _LP64
 118     // 32-bit oops don't make sense for the 64-bit VM on sparc
 119     // since the 32-bit VM has the same registers and smaller objects.
 120     Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
 121     Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
 122 #endif // _LP64
 123 #ifdef COMPILER2
 124     // Indirect branch is the same cost as direct
 125     if (FLAG_IS_DEFAULT(UseJumpTables)) {
 126       FLAG_SET_DEFAULT(UseJumpTables, true);
 127     }
 128     // Single-issue, so entry and loop tops are
 129     // aligned on a single instruction boundary
 130     if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
 131       FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
 132     }
 133     if (is_niagara_plus()) {
 134       if (has_blk_init() && UseTLAB &&
 135           FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
 136         // Use BIS instruction for TLAB allocation prefetch.
 137         FLAG_SET_ERGO(intx, AllocatePrefetchInstr, 1);
 138         if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
 139           FLAG_SET_ERGO(intx, AllocatePrefetchStyle, 3);
 140         }
 141         if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
 142           // Use smaller prefetch distance with BIS
 143           FLAG_SET_DEFAULT(AllocatePrefetchDistance, 64);
 144         }
 145       }
 146       if (is_T4()) {
 147         // Double number of prefetched cache lines on T4
 148         // since L2 cache line size is smaller (32 bytes).
 149         if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) {
 150           FLAG_SET_ERGO(intx, AllocatePrefetchLines, AllocatePrefetchLines*2);
 151         }
 152         if (FLAG_IS_DEFAULT(AllocateInstancePrefetchLines)) {
 153           FLAG_SET_ERGO(intx, AllocateInstancePrefetchLines, AllocateInstancePrefetchLines*2);
 154         }
 155       }
 156       if (AllocatePrefetchStyle != 3 && FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
 157         // Use different prefetch distance without BIS
 158         FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256);
 159       }
 160       if (AllocatePrefetchInstr == 1) {
 161         // Need a space at the end of TLAB for BIS since it
 162         // will fault when accessing memory outside of heap.
 163 
 164         // +1 for rounding up to next cache line, +1 to be safe
 165         int lines = AllocatePrefetchLines + 2;
 166         int step_size = AllocatePrefetchStepSize;
 167         int distance = AllocatePrefetchDistance;
 168         _reserve_for_allocation_prefetch = (distance + step_size*lines)/(int)HeapWordSize;
 169       }
 170     }
 171 #endif
 172   }
 173 
 174   // Use hardware population count instruction if available.
 175   if (has_hardware_popc()) {
 176     if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
 177       FLAG_SET_DEFAULT(UsePopCountInstruction, true);
 178     }
 179   } else if (UsePopCountInstruction) {
 180     warning("POPC instruction is not available on this CPU");
 181     FLAG_SET_DEFAULT(UsePopCountInstruction, false);
 182   }
 183 
 184   // T4 and newer Sparc cpus have new compare and branch instruction.
 185   if (has_cbcond()) {
 186     if (FLAG_IS_DEFAULT(UseCBCond)) {
 187       FLAG_SET_DEFAULT(UseCBCond, true);
 188     }
 189   } else if (UseCBCond) {
 190     warning("CBCOND instruction is not available on this CPU");
 191     FLAG_SET_DEFAULT(UseCBCond, false);
 192   }
 193 
 194   assert(BlockZeroingLowLimit > 0, "invalid value");
 195   if (has_block_zeroing()) {
 196     if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
 197       FLAG_SET_DEFAULT(UseBlockZeroing, true);
 198     }
 199   } else if (UseBlockZeroing) {
 200     warning("BIS zeroing instructions are not available on this CPU");
 201     FLAG_SET_DEFAULT(UseBlockZeroing, false);
 202   }
 203 
 204   assert(BlockCopyLowLimit > 0, "invalid value");
 205   if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache
 206     if (FLAG_IS_DEFAULT(UseBlockCopy)) {
 207       FLAG_SET_DEFAULT(UseBlockCopy, true);
 208     }
 209   } else if (UseBlockCopy) {
 210     warning("BIS instructions are not available or expensive on this CPU");
 211     FLAG_SET_DEFAULT(UseBlockCopy, false);
 212   }
 213 
 214 #ifdef COMPILER2
 215   // T4 and newer Sparc cpus have fast RDPC.
 216   if (has_fast_rdpc() && FLAG_IS_DEFAULT(UseRDPCForConstantTableBase)) {
 217     FLAG_SET_DEFAULT(UseRDPCForConstantTableBase, true);
 218   }
 219 
 220   // Currently not supported anywhere.
 221   FLAG_SET_DEFAULT(UseFPUForSpilling, false);
 222 
 223   MaxVectorSize = 8;
 224 
 225   assert((InteriorEntryAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 226 #endif
 227 
 228   assert((CodeEntryAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 229   assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 230 
 231   char buf[512];
 232   jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
 233                (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
 234                (has_hardware_popc() ? ", popc" : ""),
 235                (has_vis1() ? ", vis1" : ""),
 236                (has_vis2() ? ", vis2" : ""),
 237                (has_vis3() ? ", vis3" : ""),
 238                (has_blk_init() ? ", blk_init" : ""),
 239                (has_cbcond() ? ", cbcond" : ""),
 240                (has_aes() ? ", aes" : ""),
 241                (has_sha1() ? ", sha1" : ""),
 242                (has_sha256() ? ", sha256" : ""),
 243                (has_sha512() ? ", sha512" : ""),
 244                (is_ultra3() ? ", ultra3" : ""),
 245                (is_sun4v() ? ", sun4v" : ""),
 246                (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
 247                (is_sparc64() ? ", sparc64" : ""),
 248                (!has_hardware_mul32() ? ", no-mul32" : ""),
 249                (!has_hardware_div32() ? ", no-div32" : ""),
 250                (!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
 251 
 252   // buf is started with ", " or is empty
 253   _features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
 254 
 255   // There are three 64-bit SPARC families that do not overlap, e.g.,
 256   // both is_ultra3() and is_sparc64() cannot be true at the same time.
 257   // Within these families, there can be more than one chip, e.g.,
 258   // is_T4() and is_T7() machines are also is_niagara().
 259   if (is_ultra3()) {
 260     assert(_L1_data_cache_line_size == 0, "overlap with Ultra3 family");
 261     // Ref: UltraSPARC III Cu Processor
 262     _L1_data_cache_line_size = 64;
 263   }
 264   if (is_niagara()) {
 265     assert(_L1_data_cache_line_size == 0, "overlap with niagara family");
 266     // All Niagara's are sun4v's, but not all sun4v's are Niagaras, e.g.,
 267     // Fujitsu SPARC64 is sun4v, but we don't want it in this block.
 268     //
 269     // Ref: UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
 270     // Appendix F.1.3.1 Cacheable Accesses
 271     // -> 16-byte L1 cache line size
 272     //
 273     // Ref: UltraSPARC T2: A Highly-Threaded, Power-Efficient, SPARC SOC
 274     // Section III: SPARC Processor Core
 275     // -> 16-byte L1 cache line size
 276     //
 277     // Ref: Oracle's SPARC T4-1, SPARC T4-2, SPARC T4-4, and SPARC T4-1B Server Architecture
 278     // Section SPARC T4 Processor Cache Architecture
 279     // -> 32-byte L1 cache line size (no longer see that info on this ref)
 280     //
 281     // XXX - still need a T7 reference here
 282     //
 283     if (is_T7()) {  // T7 or newer
 284       _L1_data_cache_line_size = 64;
 285     } else if (is_T4()) {  // T4 or newer (until T7)
 286       _L1_data_cache_line_size = 32;
 287     } else {  // T1 or newer (until T4)
 288       _L1_data_cache_line_size = 16;
 289     }
 290   }
 291   if (is_sparc64()) {
 292     guarantee(_L1_data_cache_line_size == 0, "overlap with SPARC64 family");
 293     // Ref: Fujitsu SPARC64 VII Processor
 294     // Section 4 Cache System
 295     _L1_data_cache_line_size = 64;
 296   }
 297 
 298   // UseVIS is set to the smallest of what hardware supports and what
 299   // the command line requires.  I.e., you cannot set UseVIS to 3 on
 300   // older UltraSparc which do not support it.
 301   if (UseVIS > 3) UseVIS=3;
 302   if (UseVIS < 0) UseVIS=0;
 303   if (!has_vis3()) // Drop to 2 if no VIS3 support
 304     UseVIS = MIN2((intx)2,UseVIS);
 305   if (!has_vis2()) // Drop to 1 if no VIS2 support
 306     UseVIS = MIN2((intx)1,UseVIS);
 307   if (!has_vis1()) // Drop to 0 if no VIS1 support
 308     UseVIS = 0;
 309 
 310   // SPARC T4 and above should have support for AES instructions
 311   if (has_aes()) {
 312     if (UseVIS > 2) { // AES intrinsics use MOVxTOd/MOVdTOx which are VIS3
 313       if (FLAG_IS_DEFAULT(UseAES)) {
 314         FLAG_SET_DEFAULT(UseAES, true);
 315       }
 316       if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
 317         FLAG_SET_DEFAULT(UseAESIntrinsics, true);
 318       }
 319       // we disable both the AES flags if either of them is disabled on the command line
 320       if (!UseAES || !UseAESIntrinsics) {
 321         FLAG_SET_DEFAULT(UseAES, false);
 322         FLAG_SET_DEFAULT(UseAESIntrinsics, false);
 323       }
 324     } else {
 325         if (UseAES || UseAESIntrinsics) {
 326           warning("SPARC AES intrinsics require VIS3 instruction support. Intrinsics will be disabled.");
 327           if (UseAES) {
 328             FLAG_SET_DEFAULT(UseAES, false);
 329           }
 330           if (UseAESIntrinsics) {
 331             FLAG_SET_DEFAULT(UseAESIntrinsics, false);
 332           }
 333         }
 334     }
 335   } else if (UseAES || UseAESIntrinsics) {
 336     warning("AES instructions are not available on this CPU");
 337     if (UseAES) {
 338       FLAG_SET_DEFAULT(UseAES, false);
 339     }
 340     if (UseAESIntrinsics) {
 341       FLAG_SET_DEFAULT(UseAESIntrinsics, false);
 342     }
 343   }
 344 
 345   // SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
 346   if (has_sha1() || has_sha256() || has_sha512()) {
 347     if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
 348       if (FLAG_IS_DEFAULT(UseSHA)) {
 349         FLAG_SET_DEFAULT(UseSHA, true);
 350       }
 351     } else {
 352       if (UseSHA) {
 353         warning("SPARC SHA intrinsics require VIS1 instruction support. Intrinsics will be disabled.");
 354         FLAG_SET_DEFAULT(UseSHA, false);
 355       }
 356     }
 357   } else if (UseSHA) {
 358     warning("SHA instructions are not available on this CPU");
 359     FLAG_SET_DEFAULT(UseSHA, false);
 360   }
 361 
 362   if (!UseSHA) {
 363     FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
 364     FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
 365     FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
 366   } else {
 367     if (has_sha1()) {
 368       if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
 369         FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
 370       }
 371     } else if (UseSHA1Intrinsics) {
 372       warning("SHA1 instruction is not available on this CPU.");
 373       FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
 374     }
 375     if (has_sha256()) {
 376       if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
 377         FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
 378       }
 379     } else if (UseSHA256Intrinsics) {
 380       warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU.");
 381       FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
 382     }
 383 
 384     if (has_sha512()) {
 385       if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
 386         FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
 387       }
 388     } else if (UseSHA512Intrinsics) {
 389       warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU.");
 390       FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
 391     }
 392     if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
 393       FLAG_SET_DEFAULT(UseSHA, false);
 394     }
 395   }
 396 
 397   if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
 398     (cache_line_size > ContendedPaddingWidth))
 399     ContendedPaddingWidth = cache_line_size;
 400 
 401 #ifndef PRODUCT
 402   if (PrintMiscellaneous && Verbose) {
 403     tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
 404     tty->print("Allocation");
 405     if (AllocatePrefetchStyle <= 0) {
 406       tty->print_cr(": no prefetching");
 407     } else {
 408       tty->print(" prefetching: ");
 409       if (AllocatePrefetchInstr == 0) {
 410           tty->print("PREFETCH");
 411       } else if (AllocatePrefetchInstr == 1) {
 412           tty->print("BIS");
 413       }
 414       if (AllocatePrefetchLines > 1) {
 415         tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize);
 416       } else {
 417         tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize);
 418       }
 419     }
 420     if (PrefetchCopyIntervalInBytes > 0) {
 421       tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes);
 422     }
 423     if (PrefetchScanIntervalInBytes > 0) {
 424       tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes);
 425     }
 426     if (PrefetchFieldsAhead > 0) {
 427       tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead);
 428     }
 429     if (ContendedPaddingWidth > 0) {
 430       tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth);
 431     }
 432   }
 433 #endif // PRODUCT
 434 }
 435 
 436 void VM_Version::print_features() {
 437   tty->print_cr("Version:%s", cpu_features());
 438 }
 439 
 440 int VM_Version::determine_features() {
 441   if (UseV8InstrsOnly) {
 442     NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-V8");)
 443     return generic_v8_m;
 444   }
 445 
 446   int features = platform_features(unknown_m); // platform_features() is os_arch specific
 447 
 448   if (features == unknown_m) {
 449     features = generic_v9_m;
 450     warning("Cannot recognize SPARC version. Default to V9");
 451   }
 452 
 453   assert(is_T_family(features) == is_niagara(features), "Niagara should be T series");
 454   if (UseNiagaraInstrs) { // Force code generation for Niagara
 455     if (is_T_family(features)) {
 456       // Happy to accomodate...
 457     } else {
 458       NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Niagara");)
 459       features |= T_family_m;
 460     }
 461   } else {
 462     if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) {
 463       NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Not-Niagara");)
 464       features &= ~(T_family_m | T1_model_m);
 465     } else {
 466       // Happy to accomodate...
 467     }
 468   }
 469 
 470   return features;
 471 }
 472 
 473 static int saved_features = 0;
 474 
 475 void VM_Version::allow_all() {
 476   saved_features = _features;
 477   _features      = all_features_m;
 478 }
 479 
 480 void VM_Version::revert() {
 481   _features = saved_features;
 482 }
 483 
 484 unsigned int VM_Version::calc_parallel_worker_threads() {
 485   unsigned int result;
 486   if (is_M_series()) {
 487     // for now, use same gc thread calculation for M-series as for niagara-plus
 488     // in future, we may want to tweak parameters for nof_parallel_worker_thread
 489     result = nof_parallel_worker_threads(5, 16, 8);
 490   } else if (is_niagara_plus()) {
 491     result = nof_parallel_worker_threads(5, 16, 8);
 492   } else {
 493     result = nof_parallel_worker_threads(5, 8, 8);
 494   }
 495   return result;
 496 }