Tue, 07 Feb 2017 11:16:47 -0800
Merge
.hgtags | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Mon Jan 23 16:38:33 2017 -0800 1.2 +++ b/.hgtags Tue Feb 07 11:16:47 2017 -0800 1.3 @@ -950,4 +950,6 @@ 1.4 ef90c721a4e59b01ca36f25619010a1afe9ed4d5 jdk8u131-b02 1.5 0ca47d0811b01ecf8651b6045a1e33a4a9bed0ee jdk8u131-b03 1.6 dab1d597165207e14b6886b1823c1e990bc776a3 jdk8u131-b04 1.7 +c965fc1aa840a0903709ad69aa0e2100330ccd84 jdk8u131-b05 1.8 +6e4cfbc7534f83902692132efb61683528c04a59 jdk8u131-b06 1.9 692bc6b674dcab72453de08ee9da0856a7e41c0f jdk8u141-b00
2.1 --- a/src/os/linux/vm/globals_linux.hpp Mon Jan 23 16:38:33 2017 -0800 2.2 +++ b/src/os/linux/vm/globals_linux.hpp Tue Feb 07 11:16:47 2017 -0800 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -47,7 +47,10 @@ 2.11 "Load DLLs with executable-stack attribute in the VM Thread") \ 2.12 \ 2.13 product(bool, UseSHM, false, \ 2.14 - "Use SYSV shared memory for large pages") 2.15 + "Use SYSV shared memory for large pages") \ 2.16 + \ 2.17 + diagnostic(bool, PrintActiveCpus, false, \ 2.18 + "Print the number of CPUs detected in os::active_processor_count") 2.19 2.20 // 2.21 // Defines Linux-specific default values. The flags are available on all
3.1 --- a/src/os/linux/vm/os_linux.cpp Mon Jan 23 16:38:33 2017 -0800 3.2 +++ b/src/os/linux/vm/os_linux.cpp Tue Feb 07 11:16:47 2017 -0800 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -104,6 +104,14 @@ 3.11 3.12 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 3.13 3.14 +#ifndef _GNU_SOURCE 3.15 + #define _GNU_SOURCE 3.16 + #include <sched.h> 3.17 + #undef _GNU_SOURCE 3.18 +#else 3.19 + #include <sched.h> 3.20 +#endif 3.21 + 3.22 // if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling 3.23 // getrusage() is prepared to handle the associated failure. 3.24 #ifndef RUSAGE_THREAD 3.25 @@ -1067,29 +1075,30 @@ 3.26 3.27 // Locate initial thread stack. This special handling of initial thread stack 3.28 // is needed because pthread_getattr_np() on most (all?) Linux distros returns 3.29 -// bogus value for initial thread. 3.30 +// bogus value for the primordial process thread. While the launcher has created 3.31 +// the VM in a new thread since JDK 6, we still have to allow for the use of the 3.32 +// JNI invocation API from a primordial thread. 3.33 void os::Linux::capture_initial_stack(size_t max_size) { 3.34 - // stack size is the easy part, get it from RLIMIT_STACK 3.35 - size_t stack_size; 3.36 + 3.37 + // max_size is either 0 (which means accept OS default for thread stacks) or 3.38 + // a user-specified value known to be at least the minimum needed. If we 3.39 + // are actually on the primordial thread we can make it appear that we have a 3.40 + // smaller max_size stack by inserting the guard pages at that location. But we 3.41 + // cannot do anything to emulate a larger stack than what has been provided by 3.42 + // the OS or threading library. In fact if we try to use a stack greater than 3.43 + // what is set by rlimit then we will crash the hosting process. 3.44 + 3.45 + // Maximum stack size is the easy part, get it from RLIMIT_STACK. 3.46 + // If this is "unlimited" then it will be a huge value. 3.47 struct rlimit rlim; 3.48 getrlimit(RLIMIT_STACK, &rlim); 3.49 - stack_size = rlim.rlim_cur; 3.50 + size_t stack_size = rlim.rlim_cur; 3.51 3.52 // 6308388: a bug in ld.so will relocate its own .data section to the 3.53 // lower end of primordial stack; reduce ulimit -s value a little bit 3.54 // so we won't install guard page on ld.so's data section. 3.55 stack_size -= 2 * page_size(); 3.56 3.57 - // 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat 3.58 - // 7.1, in both cases we will get 2G in return value. 3.59 - // 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0, 3.60 - // SuSE 7.2, Debian) can not handle alternate signal stack correctly 3.61 - // for initial thread if its stack size exceeds 6M. Cap it at 2M, 3.62 - // in case other parts in glibc still assumes 2M max stack size. 3.63 - // FIXME: alt signal stack is gone, maybe we can relax this constraint? 3.64 - // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small 3.65 - if (stack_size > 2 * K * K IA64_ONLY(*2)) 3.66 - stack_size = 2 * K * K IA64_ONLY(*2); 3.67 // Try to figure out where the stack base (top) is. This is harder. 3.68 // 3.69 // When an application is started, glibc saves the initial stack pointer in 3.70 @@ -1249,14 +1258,18 @@ 3.71 // stack_top could be partially down the page so align it 3.72 stack_top = align_size_up(stack_top, page_size()); 3.73 3.74 - if (max_size && stack_size > max_size) { 3.75 - _initial_thread_stack_size = max_size; 3.76 + // Allowed stack value is minimum of max_size and what we derived from rlimit 3.77 + if (max_size > 0) { 3.78 + _initial_thread_stack_size = MIN2(max_size, stack_size); 3.79 } else { 3.80 - _initial_thread_stack_size = stack_size; 3.81 + // Accept the rlimit max, but if stack is unlimited then it will be huge, so 3.82 + // clamp it at 8MB as we do on Solaris 3.83 + _initial_thread_stack_size = MIN2(stack_size, 8*M); 3.84 } 3.85 3.86 _initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size()); 3.87 _initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size; 3.88 + assert(_initial_thread_stack_bottom < (address)stack_top, "overflow!"); 3.89 } 3.90 3.91 //////////////////////////////////////////////////////////////////////////////// 3.92 @@ -5016,12 +5029,42 @@ 3.93 } 3.94 }; 3.95 3.96 +static int os_cpu_count(const cpu_set_t* cpus) { 3.97 + int count = 0; 3.98 + // only look up to the number of configured processors 3.99 + for (int i = 0; i < os::processor_count(); i++) { 3.100 + if (CPU_ISSET(i, cpus)) { 3.101 + count++; 3.102 + } 3.103 + } 3.104 + return count; 3.105 +} 3.106 + 3.107 +// Get the current number of available processors for this process. 3.108 +// This value can change at any time during a process's lifetime. 3.109 +// sched_getaffinity gives an accurate answer as it accounts for cpusets. 3.110 +// If anything goes wrong we fallback to returning the number of online 3.111 +// processors - which can be greater than the number available to the process. 3.112 int os::active_processor_count() { 3.113 - // Linux doesn't yet have a (official) notion of processor sets, 3.114 - // so just return the number of online processors. 3.115 - int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); 3.116 - assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check"); 3.117 - return online_cpus; 3.118 + cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors 3.119 + int cpus_size = sizeof(cpu_set_t); 3.120 + int cpu_count = 0; 3.121 + 3.122 + // pid 0 means the current thread - which we have to assume represents the process 3.123 + if (sched_getaffinity(0, cpus_size, &cpus) == 0) { 3.124 + cpu_count = os_cpu_count(&cpus); 3.125 + if (PrintActiveCpus) { 3.126 + tty->print_cr("active_processor_count: sched_getaffinity processor count: %d", cpu_count); 3.127 + } 3.128 + } 3.129 + else { 3.130 + cpu_count = ::sysconf(_SC_NPROCESSORS_ONLN); 3.131 + warning("sched_getaffinity failed (%s)- using online processor count (%d) " 3.132 + "which may exceed available processors", strerror(errno), cpu_count); 3.133 + } 3.134 + 3.135 + assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check"); 3.136 + return cpu_count; 3.137 } 3.138 3.139 void os::set_native_thread_name(const char *name) {
4.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Jan 23 16:38:33 2017 -0800 4.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Feb 07 11:16:47 2017 -0800 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -631,11 +631,10 @@ 4.11 double overall_cm_overhead = 4.12 (double) MaxGCPauseMillis * marking_overhead / 4.13 (double) GCPauseIntervalMillis; 4.14 - double cpu_ratio = 1.0 / (double) os::processor_count(); 4.15 + double cpu_ratio = 1.0 / os::initial_active_processor_count(); 4.16 double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); 4.17 double marking_task_overhead = 4.18 - overall_cm_overhead / marking_thread_num * 4.19 - (double) os::processor_count(); 4.20 + overall_cm_overhead / marking_thread_num * os::initial_active_processor_count(); 4.21 double sleep_factor = 4.22 (1.0 - marking_task_overhead) / marking_task_overhead; 4.23
5.1 --- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Mon Jan 23 16:38:33 2017 -0800 5.2 +++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Tue Feb 07 11:16:47 2017 -0800 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -80,7 +80,7 @@ 5.11 5.12 // Determines how many mutator threads can process the buffers in parallel. 5.13 uint DirtyCardQueueSet::num_par_ids() { 5.14 - return (uint)os::processor_count(); 5.15 + return (uint)os::initial_active_processor_count(); 5.16 } 5.17 5.18 void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
6.1 --- a/src/share/vm/runtime/arguments.cpp Mon Jan 23 16:38:33 2017 -0800 6.2 +++ b/src/share/vm/runtime/arguments.cpp Tue Feb 07 11:16:47 2017 -0800 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -1768,10 +1768,39 @@ 6.11 FLAG_SET_CMDLINE(uintx, MaxRAMFraction, DefaultMaxRAMFraction); 6.12 } 6.13 6.14 - const julong phys_mem = 6.15 + julong phys_mem = 6.16 FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM) 6.17 : (julong)MaxRAM; 6.18 6.19 + // Experimental support for CGroup memory limits 6.20 + if (UseCGroupMemoryLimitForHeap) { 6.21 + // This is a rough indicator that a CGroup limit may be in force 6.22 + // for this process 6.23 + const char* lim_file = "/sys/fs/cgroup/memory/memory.limit_in_bytes"; 6.24 + FILE *fp = fopen(lim_file, "r"); 6.25 + if (fp != NULL) { 6.26 + julong cgroup_max = 0; 6.27 + int ret = fscanf(fp, JULONG_FORMAT, &cgroup_max); 6.28 + if (ret == 1 && cgroup_max > 0) { 6.29 + // If unlimited, cgroup_max will be a very large, but unspecified 6.30 + // value, so use initial phys_mem as a limit 6.31 + if (PrintGCDetails && Verbose) { 6.32 + // Cannot use gclog_or_tty yet. 6.33 + tty->print_cr("Setting phys_mem to the min of cgroup limit (" 6.34 + JULONG_FORMAT "MB) and initial phys_mem (" 6.35 + JULONG_FORMAT "MB)", cgroup_max/M, phys_mem/M); 6.36 + } 6.37 + phys_mem = MIN2(cgroup_max, phys_mem); 6.38 + } else { 6.39 + warning("Unable to read/parse cgroup memory limit from %s: %s", 6.40 + lim_file, errno != 0 ? strerror(errno) : "unknown error"); 6.41 + } 6.42 + fclose(fp); 6.43 + } else { 6.44 + warning("Unable to open cgroup memory limit file %s (%s)", lim_file, strerror(errno)); 6.45 + } 6.46 + } 6.47 + 6.48 // If the maximum heap size has not been set with -Xmx, 6.49 // then set it as fraction of the size of physical memory, 6.50 // respecting the maximum and minimum sizes of the heap.
7.1 --- a/src/share/vm/runtime/globals.hpp Mon Jan 23 16:38:33 2017 -0800 7.2 +++ b/src/share/vm/runtime/globals.hpp Tue Feb 07 11:16:47 2017 -0800 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 7.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -2068,6 +2068,10 @@ 7.11 "Maximum ergonomically set heap size (in bytes); zero means use " \ 7.12 "MaxRAM / MaxRAMFraction") \ 7.13 \ 7.14 + experimental(bool, UseCGroupMemoryLimitForHeap, false, \ 7.15 + "Use CGroup memory limit as physical memory limit for heap " \ 7.16 + "sizing") \ 7.17 + \ 7.18 product(uintx, MaxRAMFraction, 4, \ 7.19 "Maximum fraction (1/n) of real memory used for maximum heap " \ 7.20 "size") \
8.1 --- a/src/share/vm/runtime/os.cpp Mon Jan 23 16:38:33 2017 -0800 8.2 +++ b/src/share/vm/runtime/os.cpp Tue Feb 07 11:16:47 2017 -0800 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 8.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -78,6 +78,7 @@ 8.11 uintptr_t os::_serialize_page_mask = 0; 8.12 long os::_rand_seed = 1; 8.13 int os::_processor_count = 0; 8.14 +int os::_initial_active_processor_count = 0; 8.15 size_t os::_page_sizes[os::page_sizes_max]; 8.16 8.17 #ifndef PRODUCT 8.18 @@ -322,6 +323,7 @@ 8.19 } 8.20 8.21 void os::init_before_ergo() { 8.22 + initialize_initial_active_processor_count(); 8.23 // We need to initialize large page support here because ergonomics takes some 8.24 // decisions depending on large page support and the calculated large page size. 8.25 large_page_init(); 8.26 @@ -835,7 +837,11 @@ 8.27 st->print("CPU:"); 8.28 st->print("total %d", os::processor_count()); 8.29 // It's not safe to query number of active processors after crash 8.30 - // st->print("(active %d)", os::active_processor_count()); 8.31 + // st->print("(active %d)", os::active_processor_count()); but we can 8.32 + // print the initial number of active processors. 8.33 + // We access the raw value here because the assert in the accessor will 8.34 + // fail if the crash occurs before initialization of this value. 8.35 + st->print(" (initial active %d)", _initial_active_processor_count); 8.36 st->print(" %s", VM_Version::cpu_features()); 8.37 st->cr(); 8.38 pd_print_cpu_info(st); 8.39 @@ -1418,6 +1424,11 @@ 8.40 return result; 8.41 } 8.42 8.43 +void os::initialize_initial_active_processor_count() { 8.44 + assert(_initial_active_processor_count == 0, "Initial active processor count already set."); 8.45 + _initial_active_processor_count = active_processor_count(); 8.46 +} 8.47 + 8.48 void os::SuspendedThreadTask::run() { 8.49 assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this"); 8.50 internal_do_task();
9.1 --- a/src/share/vm/runtime/os.hpp Mon Jan 23 16:38:33 2017 -0800 9.2 +++ b/src/share/vm/runtime/os.hpp Tue Feb 07 11:16:47 2017 -0800 9.3 @@ -151,6 +151,7 @@ 9.4 9.5 static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); 9.6 9.7 + static void initialize_initial_active_processor_count(); 9.8 public: 9.9 static void init(void); // Called before command line parsing 9.10 static void init_before_ergo(void); // Called after command line parsing 9.11 @@ -238,6 +239,13 @@ 9.12 // Note that on some OSes this can change dynamically. 9.13 static int active_processor_count(); 9.14 9.15 + // At startup the number of active CPUs this process is allowed to run on. 9.16 + // This value does not change dynamically. May be different from active_processor_count(). 9.17 + static int initial_active_processor_count() { 9.18 + assert(_initial_active_processor_count > 0, "Initial active processor count not set yet."); 9.19 + return _initial_active_processor_count; 9.20 + } 9.21 + 9.22 // Bind processes to processors. 9.23 // This is a two step procedure: 9.24 // first you generate a distribution of processes to processors, 9.25 @@ -975,8 +983,9 @@ 9.26 9.27 9.28 protected: 9.29 - static long _rand_seed; // seed for random number generator 9.30 - static int _processor_count; // number of processors 9.31 + static long _rand_seed; // seed for random number generator 9.32 + static int _processor_count; // number of processors 9.33 + static int _initial_active_processor_count; // number of active processors during initialization. 9.34 9.35 static char* format_boot_path(const char* format_string, 9.36 const char* home,
10.1 --- a/src/share/vm/runtime/vm_version.cpp Mon Jan 23 16:38:33 2017 -0800 10.2 +++ b/src/share/vm/runtime/vm_version.cpp Tue Feb 07 11:16:47 2017 -0800 10.3 @@ -1,5 +1,5 @@ 10.4 /* 10.5 - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 10.6 + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 10.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.8 * 10.9 * This code is free software; you can redistribute it and/or modify it 10.10 @@ -296,7 +296,7 @@ 10.11 // processor after the first 8. For example, on a 72 cpu machine 10.12 // and a chosen fraction of 5/8 10.13 // use 8 + (72 - 8) * (5/8) == 48 worker threads. 10.14 - unsigned int ncpus = (unsigned int) os::active_processor_count(); 10.15 + unsigned int ncpus = (unsigned int) os::initial_active_processor_count(); 10.16 return (ncpus <= switch_pt) ? 10.17 ncpus : 10.18 (switch_pt + ((ncpus - switch_pt) * num) / den);
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/runtime/os/AvailableProcessors.java Tue Feb 07 11:16:47 2017 -0800 11.3 @@ -0,0 +1,103 @@ 11.4 +/* 11.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + */ 11.26 +import java.io.File; 11.27 +import com.oracle.java.testlibrary.ProcessTools; 11.28 +import com.oracle.java.testlibrary.OutputAnalyzer; 11.29 +import java.util.ArrayList; 11.30 + 11.31 +/* 11.32 + * @test 11.33 + * @bug 6515172 11.34 + * @summary Check that availableProcessors reports the correct value when running in a cpuset on linux 11.35 + * @requires os.family == "linux" 11.36 + * @library /testlibrary 11.37 + * @build com.oracle.java.testlibrary.* 11.38 + * @run driver AvailableProcessors 11.39 + */ 11.40 +public class AvailableProcessors { 11.41 + 11.42 + static final String SUCCESS_STRING = "Found expected processors: "; 11.43 + 11.44 + public static void main(String[] args) throws Throwable { 11.45 + if (args.length > 0) 11.46 + checkProcessors(Integer.parseInt(args[0])); 11.47 + else { 11.48 + // run ourselves under different cpu configurations 11.49 + // using the taskset command 11.50 + String taskset; 11.51 + final String taskset1 = "/bin/taskset"; 11.52 + final String taskset2 = "/usr/bin/taskset"; 11.53 + if (new File(taskset1).exists()) 11.54 + taskset = taskset1; 11.55 + else if (new File(taskset2).exists()) 11.56 + taskset = taskset2; 11.57 + else { 11.58 + System.out.println("Skipping test: could not find taskset command"); 11.59 + return; 11.60 + } 11.61 + 11.62 + int available = Runtime.getRuntime().availableProcessors(); 11.63 + 11.64 + if (available == 1) { 11.65 + System.out.println("Skipping test: only one processor available"); 11.66 + return; 11.67 + } 11.68 + 11.69 + // Get the java command we want to execute 11.70 + // Enable logging for easier failure diagnosis 11.71 + ProcessBuilder master = 11.72 + ProcessTools.createJavaProcessBuilder(false, 11.73 + "-XX:+UnlockDiagnosticVMOptions", 11.74 + "-XX:+PrintActiveCpus", 11.75 + "AvailableProcessors"); 11.76 + 11.77 + int[] expected = new int[] { 1, available/2, available-1, available }; 11.78 + 11.79 + for (int i : expected) { 11.80 + System.out.println("Testing for " + i + " processors ..."); 11.81 + int max = i - 1; 11.82 + ArrayList<String> cmdline = new ArrayList<>(master.command()); 11.83 + // prepend taskset command 11.84 + cmdline.add(0, "0-" + max); 11.85 + cmdline.add(0, "-c"); 11.86 + cmdline.add(0, taskset); 11.87 + // append expected processor count 11.88 + cmdline.add(String.valueOf(i)); 11.89 + ProcessBuilder pb = new ProcessBuilder(cmdline); 11.90 + System.out.println("Final command line: " + 11.91 + ProcessTools.getCommandLine(pb)); 11.92 + OutputAnalyzer output = ProcessTools.executeProcess(pb); 11.93 + output.shouldContain(SUCCESS_STRING); 11.94 + } 11.95 + } 11.96 + } 11.97 + 11.98 + static void checkProcessors(int expected) { 11.99 + int available = Runtime.getRuntime().availableProcessors(); 11.100 + if (available != expected) 11.101 + throw new Error("Expected " + expected + " processors, but found " 11.102 + + available); 11.103 + else 11.104 + System.out.println(SUCCESS_STRING + available); 11.105 + } 11.106 +}